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;
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     (void)mkfifo(filename, 0644);
01738     fd = SYS_OpenFile(filename, O_RDONLY | O_NONBLOCK, 0);
01739 
01740     FD_ZERO(&read_fd);
01741     FD_SET(fd, &read_fd);
01742     
01743     (void)select(fd+1, &read_fd, NULL, NULL, ptv);
01744 
01745     (void)SYS_ReadFile(fd, buf, 1);
01746     (void)SYS_CloseFile(fd);
01747     (void)SYS_RemoveFile(filename);
01748 
01749     if (INFINITE != dwTime)
01750     {
01751         long int diff;
01752 
01753         gettimeofday(&after, NULL);
01754         diff = time_sub(&after, &before);
01755         dwTime -= diff/1000;
01756     }
01757 
01758     return dwTime;
01759 }
01760 
01852 LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout,
01853     LPSCARD_READERSTATE_A rgReaderStates, DWORD cReaders)
01854 {
01855     PSCARD_READERSTATE_A currReader;
01856     PREADER_STATE rContext;
01857     long dwTime = dwTimeout;
01858     DWORD dwState;
01859     DWORD dwBreakFlag = 0;
01860     int j;
01861     LONG dwContextIndex;
01862     int currentReaderCount = 0;
01863     LONG rv = SCARD_S_SUCCESS;
01864 
01865     PROFILE_START
01866 
01867     if ((rgReaderStates == NULL && cReaders > 0)
01868         || (cReaders > PCSCLITE_MAX_READERS_CONTEXTS))
01869         return SCARD_E_INVALID_PARAMETER;
01870 
01871     /* Check the integrity of the reader states structures */
01872     for (j = 0; j < cReaders; j++)
01873     {
01874         if (rgReaderStates[j].szReader == NULL)
01875             return SCARD_E_INVALID_VALUE;
01876     }
01877 
01878     /* return if all readers are SCARD_STATE_IGNORE */
01879     if (cReaders > 0)
01880     {
01881         int nbNonIgnoredReaders = cReaders;
01882 
01883         for (j=0; j<cReaders; j++)
01884             if (rgReaderStates[j].dwCurrentState & SCARD_STATE_IGNORE)
01885                 nbNonIgnoredReaders--;
01886 
01887         if (0 == nbNonIgnoredReaders)
01888             return SCARD_S_SUCCESS;
01889     }
01890 
01891     rv = SCardCheckDaemonAvailability();
01892     if (rv != SCARD_S_SUCCESS)
01893         return rv;
01894 
01895     /*
01896      * Make sure this context has been opened
01897      */
01898     dwContextIndex = SCardGetContextIndice(hContext);
01899     if (dwContextIndex == -1)
01900         return SCARD_E_INVALID_HANDLE;
01901 
01902     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01903 
01904     /* check the context is still opened */
01905     dwContextIndex = SCardGetContextIndice(hContext);
01906     if (dwContextIndex == -1)
01907         /* the context is now invalid
01908          * -> another thread may have called SCardReleaseContext
01909          * -> so the mMutex has been unlocked */
01910         return SCARD_E_INVALID_HANDLE;
01911 
01912     /*
01913      * Application is waiting for a reader - return the first available
01914      * reader
01915      * This is DEPRECATED. Use the special reader name \\?PnP?\Notification
01916      * instead
01917      */
01918     if (cReaders == 0)
01919     {
01920         while (1)
01921         {
01922             int i;
01923 
01924             rv = SCardCheckDaemonAvailability();
01925             if (rv != SCARD_S_SUCCESS)
01926                 goto end;
01927 
01928             for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01929             {
01930                 if ((readerStates[i])->readerID != 0)
01931                 {
01932                     /* Reader was found */
01933                     rv = SCARD_S_SUCCESS;
01934                     goto end;
01935                 }
01936             }
01937 
01938             if (dwTimeout == 0)
01939             {
01940                 /* return immediately - no reader available */
01941                 rv = SCARD_E_READER_UNAVAILABLE;
01942                 goto end;
01943             }
01944 
01945             dwTime = WaitForPcscdEvent(hContext, dwTime);
01946             if (dwTimeout != INFINITE)
01947             {
01948                 if (dwTime <= 0)
01949                 {
01950                     rv = SCARD_E_TIMEOUT;
01951                     goto end;
01952                 }
01953             }
01954         }
01955     }
01956 
01957     /*
01958      * End of search for readers
01959      */
01960 
01961     /* Clear the event state for all readers */
01962     for (j = 0; j < cReaders; j++)
01963         rgReaderStates[j].dwEventState = 0;
01964 
01965     /* Now is where we start our event checking loop */
01966     Log1(PCSC_LOG_DEBUG, "Event Loop Start");
01967 
01968     psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_BLOCKING;
01969 
01970     /* Get the initial reader count on the system */
01971     for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++)
01972         if ((readerStates[j])->readerID != 0)
01973             currentReaderCount++;
01974 
01975     j = 0;
01976     do
01977     {
01978         rv = SCardCheckDaemonAvailability();
01979         if (rv != SCARD_S_SUCCESS)
01980         {
01981             if (psContextMap[dwContextIndex].mMutex)
01982                 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01983 
01984             PROFILE_END(rv)
01985 
01986             return rv;
01987         }
01988 
01989         currReader = &rgReaderStates[j];
01990 
01991         /* Ignore for IGNORED readers */
01992         if (!(currReader->dwCurrentState & SCARD_STATE_IGNORE))
01993         {
01994             LPSTR lpcReaderName;
01995             int i;
01996 
01997       /************ Looks for correct readernames *********************/
01998 
01999             lpcReaderName = (char *) currReader->szReader;
02000 
02001             for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02002             {
02003                 if (strcmp(lpcReaderName, (readerStates[i])->readerName) == 0)
02004                     break;
02005             }
02006 
02007             /* The requested reader name is not recognized */
02008             if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02009             {
02010                 /* PnP special reader? */
02011                 if (strcasecmp(lpcReaderName, "\\\\?PnP?\\Notification") == 0)
02012                 {
02013                     int k, newReaderCount = 0;
02014 
02015                     for (k=0; k < PCSCLITE_MAX_READERS_CONTEXTS; k++)
02016                         if ((readerStates[k])->readerID != 0)
02017                             newReaderCount++;
02018 
02019                     if (newReaderCount != currentReaderCount)
02020                     {
02021                         Log1(PCSC_LOG_INFO, "Reader list changed");
02022                         currentReaderCount = newReaderCount;
02023 
02024                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02025                         dwBreakFlag = 1;
02026                     }
02027                 }
02028                 else
02029                 {
02030                     currReader->dwEventState = SCARD_STATE_UNKNOWN | SCARD_STATE_UNAVAILABLE;
02031                     if (!(currReader->dwCurrentState & SCARD_STATE_UNKNOWN))
02032                     {
02033                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02034                         /*
02035                          * Spec says use SCARD_STATE_IGNORE but a removed USB
02036                          * reader with eventState fed into currentState will
02037                          * be ignored forever
02038                          */
02039                         dwBreakFlag = 1;
02040                     }
02041                 }
02042             }
02043             else
02044             {
02045                 /* The reader has come back after being away */
02046                 if (currReader->dwCurrentState & SCARD_STATE_UNKNOWN)
02047                 {
02048                     currReader->dwEventState |= SCARD_STATE_CHANGED;
02049                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
02050                     dwBreakFlag = 1;
02051                 }
02052 
02053     /*****************************************************************/
02054 
02055                 /* Set the reader status structure */
02056                 rContext = readerStates[i];
02057 
02058                 /* Now we check all the Reader States */
02059                 dwState = rContext->readerState;
02060                 {
02061                     int currentCounter, stateCounter;
02062 
02063                     stateCounter = (dwState >> 16) & 0xFFFF;
02064                     currentCounter = (currReader->dwCurrentState >> 16) & 0xFFFF;
02065 
02066                     /* has the event counter changed since the last call? */
02067                     if (stateCounter != currentCounter)
02068                     {
02069                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02070                         dwBreakFlag = 1;
02071                     }
02072 
02073                     /* add an event counter in the upper word of dwEventState */
02074                     currReader->dwEventState =
02075                         ((currReader->dwEventState & 0xffff )
02076                         | (stateCounter << 16));
02077                 }
02078 
02079     /*********** Check if the reader is in the correct state ********/
02080                 if (dwState & SCARD_UNKNOWN)
02081                 {
02082                     /* reader is in bad state */
02083                     currReader->dwEventState = SCARD_STATE_UNAVAILABLE;
02084                     if (!(currReader->dwCurrentState & SCARD_STATE_UNAVAILABLE))
02085                     {
02086                         /* App thinks reader is in good state and it is not */
02087                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02088                         dwBreakFlag = 1;
02089                     }
02090                 }
02091                 else
02092                 {
02093                     /* App thinks reader in bad state but it is not */
02094                     if (currReader-> dwCurrentState & SCARD_STATE_UNAVAILABLE)
02095                     {
02096                         currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
02097                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02098                         dwBreakFlag = 1;
02099                     }
02100                 }
02101 
02102     /********** Check for card presence in the reader **************/
02103 
02104                 if (dwState & SCARD_PRESENT)
02105                 {
02106                     /* card present but not yet powered up */
02107                     if (0 == rContext->cardAtrLength)
02108                         /* Allow the status thread to convey information */
02109                         (void)SYS_USleep(PCSCLITE_STATUS_POLL_RATE + 10);
02110 
02111                     currReader->cbAtr = rContext->cardAtrLength;
02112                     memcpy(currReader->rgbAtr, rContext->cardAtr,
02113                         currReader->cbAtr);
02114                 }
02115                 else
02116                     currReader->cbAtr = 0;
02117 
02118                 /* Card is now absent */
02119                 if (dwState & SCARD_ABSENT)
02120                 {
02121                     currReader->dwEventState |= SCARD_STATE_EMPTY;
02122                     currReader->dwEventState &= ~SCARD_STATE_PRESENT;
02123                     currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
02124                     currReader->dwEventState &= ~SCARD_STATE_IGNORE;
02125                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
02126                     currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
02127                     currReader->dwEventState &= ~SCARD_STATE_ATRMATCH;
02128                     currReader->dwEventState &= ~SCARD_STATE_MUTE;
02129                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
02130 
02131                     /* After present the rest are assumed */
02132                     if (currReader->dwCurrentState & SCARD_STATE_PRESENT)
02133                     {
02134                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02135                         dwBreakFlag = 1;
02136                     }
02137                 }
02138                 /* Card is now present */
02139                 else if (dwState & SCARD_PRESENT)
02140                 {
02141                     currReader->dwEventState |= SCARD_STATE_PRESENT;
02142                     currReader->dwEventState &= ~SCARD_STATE_EMPTY;
02143                     currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
02144                     currReader->dwEventState &= ~SCARD_STATE_IGNORE;
02145                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
02146                     currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
02147                     currReader->dwEventState &= ~SCARD_STATE_MUTE;
02148 
02149                     if (currReader->dwCurrentState & SCARD_STATE_EMPTY)
02150                     {
02151                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02152                         dwBreakFlag = 1;
02153                     }
02154 
02155                     if (dwState & SCARD_SWALLOWED)
02156                     {
02157                         currReader->dwEventState |= SCARD_STATE_MUTE;
02158                         if (!(currReader->dwCurrentState & SCARD_STATE_MUTE))
02159                         {
02160                             currReader->dwEventState |= SCARD_STATE_CHANGED;
02161                             dwBreakFlag = 1;
02162                         }
02163                     }
02164                     else
02165                     {
02166                         /* App thinks card is mute but it is not */
02167                         if (currReader->dwCurrentState & SCARD_STATE_MUTE)
02168                         {
02169                             currReader->dwEventState |= SCARD_STATE_CHANGED;
02170                             dwBreakFlag = 1;
02171                         }
02172                     }
02173                 }
02174 
02175                 /* Now figure out sharing modes */
02176                 if (rContext->readerSharing == -1)
02177                 {
02178                     currReader->dwEventState |= SCARD_STATE_EXCLUSIVE;
02179                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
02180                     if (currReader->dwCurrentState & SCARD_STATE_INUSE)
02181                     {
02182                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02183                         dwBreakFlag = 1;
02184                     }
02185                 }
02186                 else if (rContext->readerSharing >= 1)
02187                 {
02188                     /* A card must be inserted for it to be INUSE */
02189                     if (dwState & SCARD_PRESENT)
02190                     {
02191                         currReader->dwEventState |= SCARD_STATE_INUSE;
02192                         currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
02193                         if (currReader-> dwCurrentState & SCARD_STATE_EXCLUSIVE)
02194                         {
02195                             currReader->dwEventState |= SCARD_STATE_CHANGED;
02196                             dwBreakFlag = 1;
02197                         }
02198                     }
02199                 }
02200                 else if (rContext->readerSharing == 0)
02201                 {
02202                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
02203                     currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
02204 
02205                     if (currReader->dwCurrentState & SCARD_STATE_INUSE)
02206                     {
02207                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02208                         dwBreakFlag = 1;
02209                     }
02210                     else if (currReader-> dwCurrentState
02211                         & SCARD_STATE_EXCLUSIVE)
02212                     {
02213                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02214                         dwBreakFlag = 1;
02215                     }
02216                 }
02217 
02218                 if (currReader->dwCurrentState == SCARD_STATE_UNAWARE)
02219                 {
02220                     /*
02221                      * Break out of the while .. loop and return status
02222                      * once all the status's for all readers is met
02223                      */
02224                     currReader->dwEventState |= SCARD_STATE_CHANGED;
02225                     dwBreakFlag = 1;
02226                 }
02227             }   /* End of SCARD_STATE_UNKNOWN */
02228         }   /* End of SCARD_STATE_IGNORE */
02229 
02230         /* Counter and resetter */
02231         j++;
02232         if (j == cReaders)
02233         {
02234             /* go back to the first reader */
02235             j = 0;
02236 
02237             /* Declare all the break conditions */
02238 
02239             /* Break if UNAWARE is set and all readers have been checked */
02240             if (dwBreakFlag == 1)
02241                 break;
02242 
02243             if (BLOCK_STATUS_RESUME
02244                 == psContextMap[dwContextIndex].contextBlockStatus)
02245                 break;
02246 
02247             /* Only sleep once for each cycle of reader checks. */
02248             dwTime = WaitForPcscdEvent(hContext, dwTime);
02249 
02250             if (dwTimeout != INFINITE)
02251             {
02252                 /* If time is greater than timeout and all readers have been
02253                  * checked
02254                  */
02255                 if (dwTime <= 0)
02256                 {
02257                     rv = SCARD_E_TIMEOUT;
02258                     goto end;
02259                 }
02260             }
02261         }
02262     }
02263     while (1);
02264 
02265     if (psContextMap[dwContextIndex].contextBlockStatus == BLOCK_STATUS_RESUME)
02266         rv = SCARD_E_CANCELLED;
02267 
02268 end:
02269     Log1(PCSC_LOG_DEBUG, "Event Loop End");
02270 
02271     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02272 
02273     PROFILE_END(rv)
02274 
02275     return rv;
02276 }
02277 
02329 LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,
02330     DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
02331     LPDWORD lpBytesReturned)
02332 {
02333     LONG rv;
02334     control_struct scControlStruct;
02335     sharedSegmentMsg msgStruct;
02336     int i;
02337     DWORD dwContextIndex, dwChannelIndex;
02338 
02339     PROFILE_START
02340 
02341     /* 0 bytes received by default */
02342     if (NULL != lpBytesReturned)
02343         *lpBytesReturned = 0;
02344 
02345     rv = SCardCheckDaemonAvailability();
02346     if (rv != SCARD_S_SUCCESS)
02347         return rv;
02348 
02349     /*
02350      * Make sure this handle has been opened
02351      */
02352     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02353     if (rv == -1)
02354         return SCARD_E_INVALID_HANDLE;
02355 
02356     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
02357 
02358     /* check the handle is still valid */
02359     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02360     if (rv == -1)
02361         /* the handle is now invalid
02362          * -> another thread may have called SCardReleaseContext
02363          * -> so the mMutex has been unlocked */
02364         return SCARD_E_INVALID_HANDLE;
02365 
02366     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02367     {
02368         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02369 
02370         /* by default r == NULL */
02371         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02372             break;
02373     }
02374 
02375     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02376     {
02377         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02378         return SCARD_E_READER_UNAVAILABLE;
02379     }
02380 
02381     if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
02382         || (cbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
02383     {
02384         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02385         return SCARD_E_INSUFFICIENT_BUFFER;
02386     }
02387 
02388     if ((cbSendLength > MAX_BUFFER_SIZE) || (cbRecvLength > MAX_BUFFER_SIZE))
02389     {
02390         /* extended control */
02391         unsigned char buffer[sizeof(sharedSegmentMsg) + MAX_BUFFER_SIZE_EXTENDED];
02392         control_struct_extended *scControlStructExtended = (control_struct_extended *)buffer;
02393         sharedSegmentMsg *pmsgStruct = (psharedSegmentMsg)buffer;
02394 
02395         scControlStructExtended->hCard = hCard;
02396         scControlStructExtended->dwControlCode = dwControlCode;
02397         scControlStructExtended->cbSendLength = cbSendLength;
02398         scControlStructExtended->cbRecvLength = cbRecvLength;
02399         scControlStructExtended->pdwBytesReturned = 0;
02400         scControlStructExtended->rv = SCARD_S_SUCCESS;
02401         /* The size of data to send is the size of
02402          * struct control_struct_extended WITHOUT the data[] field
02403          * plus the effective data[] size
02404          */
02405         scControlStructExtended->size = sizeof(*scControlStructExtended)
02406             - (sizeof(control_struct_extended) - offsetof(control_struct_extended, data))
02407             + cbSendLength;
02408         memcpy(scControlStructExtended->data, pbSendBuffer, cbSendLength);
02409 
02410         rv = WrapSHMWrite(SCARD_CONTROL_EXTENDED,
02411             psContextMap[dwContextIndex].dwClientID,
02412             scControlStructExtended->size,
02413             PCSCLITE_CLIENT_ATTEMPTS, buffer);
02414 
02415         if (rv == -1)
02416         {
02417             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02418             return SCARD_E_NO_SERVICE;
02419         }
02420 
02421         /*
02422          * Read a message from the server
02423          */
02424         /* read the first block */
02425         rv = SHMMessageReceive(buffer, sizeof(sharedSegmentMsg),
02426             psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
02427         if (rv == -1)
02428         {
02429             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02430             return SCARD_F_COMM_ERROR;
02431         }
02432 
02433         /* we receive a sharedSegmentMsg and not a control_struct_extended */
02434         scControlStructExtended = (control_struct_extended *)&(pmsgStruct -> data);
02435 
02436         /* a second block is present */
02437         if (scControlStructExtended->size > PCSCLITE_MAX_MESSAGE_SIZE)
02438         {
02439             rv = SHMMessageReceive(buffer + sizeof(sharedSegmentMsg),
02440                 scControlStructExtended->size-PCSCLITE_MAX_MESSAGE_SIZE,
02441                 psContextMap[dwContextIndex].dwClientID,
02442                 PCSCLITE_CLIENT_ATTEMPTS);
02443             if (rv == -1)
02444             {
02445                 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02446                 return SCARD_F_COMM_ERROR;
02447             }
02448         }
02449 
02450         if (scControlStructExtended -> rv == SCARD_S_SUCCESS)
02451         {
02452             /*
02453              * Copy and zero it so any secret information is not leaked
02454              */
02455             memcpy(pbRecvBuffer, scControlStructExtended -> data,
02456                 scControlStructExtended -> pdwBytesReturned);
02457             memset(scControlStructExtended -> data, 0x00,
02458                 scControlStructExtended -> pdwBytesReturned);
02459         }
02460 
02461         if (NULL != lpBytesReturned)
02462             *lpBytesReturned = scControlStructExtended -> pdwBytesReturned;
02463 
02464         rv = scControlStructExtended -> rv;
02465     }
02466     else
02467     {
02468         scControlStruct.hCard = hCard;
02469         scControlStruct.dwControlCode = dwControlCode;
02470         scControlStruct.cbSendLength = cbSendLength;
02471         scControlStruct.cbRecvLength = cbRecvLength;
02472         memcpy(scControlStruct.pbSendBuffer, pbSendBuffer, cbSendLength);
02473 
02474         rv = WrapSHMWrite(SCARD_CONTROL,
02475             psContextMap[dwContextIndex].dwClientID,
02476             sizeof(scControlStruct), PCSCLITE_CLIENT_ATTEMPTS, &scControlStruct);
02477 
02478         if (rv == -1)
02479         {
02480             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02481             return SCARD_E_NO_SERVICE;
02482         }
02483 
02484         /*
02485          * Read a message from the server
02486          */
02487         rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
02488             PCSCLITE_CLIENT_ATTEMPTS);
02489 
02490         if (rv == -1)
02491         {
02492             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02493             return SCARD_F_COMM_ERROR;
02494         }
02495 
02496         memcpy(&scControlStruct, &msgStruct.data, sizeof(scControlStruct));
02497 
02498         if (NULL != lpBytesReturned)
02499             *lpBytesReturned = scControlStruct.dwBytesReturned;
02500 
02501         if (scControlStruct.rv == SCARD_S_SUCCESS)
02502         {
02503             /*
02504              * Copy and zero it so any secret information is not leaked
02505              */
02506             memcpy(pbRecvBuffer, scControlStruct.pbRecvBuffer,
02507                 scControlStruct.cbRecvLength);
02508             memset(scControlStruct.pbRecvBuffer, 0x00,
02509                 sizeof(scControlStruct.pbRecvBuffer));
02510         }
02511 
02512         rv = scControlStruct.rv;
02513     }
02514 
02515     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02516 
02517     PROFILE_END(rv)
02518 
02519     return rv;
02520 }
02521 
02621 LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr,
02622     LPDWORD pcbAttrLen)
02623 {
02624     LONG ret;
02625     unsigned char *buf = NULL;
02626 
02627     PROFILE_START
02628 
02629     if (NULL == pcbAttrLen)
02630         return SCARD_E_INVALID_PARAMETER;
02631 
02632     if (SCARD_AUTOALLOCATE == *pcbAttrLen)
02633     {
02634         if (NULL == pbAttr)
02635             return SCARD_E_INVALID_PARAMETER;
02636 
02637         *pcbAttrLen = MAX_BUFFER_SIZE;
02638         buf = malloc(*pcbAttrLen);
02639         if (NULL == buf)
02640             return SCARD_E_NO_MEMORY;
02641 
02642         *(unsigned char **)pbAttr = buf;
02643     }
02644     else
02645     {
02646         buf = pbAttr;
02647 
02648         /* if only get the length */
02649         if (NULL == pbAttr)
02650             /* use a reasonable size */
02651             *pcbAttrLen = MAX_BUFFER_SIZE;
02652     }
02653 
02654     ret = SCardGetSetAttrib(hCard, SCARD_GET_ATTRIB, dwAttrId, buf,
02655         pcbAttrLen);
02656 
02657     PROFILE_END(ret)
02658 
02659     return ret;
02660 }
02661 
02696 LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr,
02697     DWORD cbAttrLen)
02698 {
02699     LONG ret;
02700 
02701     PROFILE_START
02702 
02703     if (NULL == pbAttr || 0 == cbAttrLen)
02704         return SCARD_E_INVALID_PARAMETER;
02705 
02706     ret = SCardGetSetAttrib(hCard, SCARD_SET_ATTRIB, dwAttrId, (LPBYTE)pbAttr,
02707         &cbAttrLen);
02708 
02709     PROFILE_END(ret)
02710 
02711     return ret;
02712 }
02713 
02714 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
02715     LPBYTE pbAttr, LPDWORD pcbAttrLen)
02716 {
02717     LONG rv;
02718     getset_struct scGetSetStruct;
02719     sharedSegmentMsg msgStruct;
02720     int i;
02721     DWORD dwContextIndex, dwChannelIndex;
02722 
02723     rv = SCardCheckDaemonAvailability();
02724     if (rv != SCARD_S_SUCCESS)
02725         return rv;
02726 
02727     /*
02728      * Make sure this handle has been opened
02729      */
02730     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02731     if (rv == -1)
02732         return SCARD_E_INVALID_HANDLE;
02733 
02734     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
02735 
02736     /* check the handle is still valid */
02737     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02738     if (rv == -1)
02739         /* the handle is now invalid
02740          * -> another thread may have called SCardReleaseContext
02741          * -> so the mMutex has been unlocked */
02742         return SCARD_E_INVALID_HANDLE;
02743 
02744     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02745     {
02746         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02747 
02748         /* by default r == NULL */
02749         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02750             break;
02751     }
02752 
02753     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02754     {
02755         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02756         return SCARD_E_READER_UNAVAILABLE;
02757     }
02758 
02759     if (*pcbAttrLen > MAX_BUFFER_SIZE)
02760     {
02761         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02762         return SCARD_E_INSUFFICIENT_BUFFER;
02763     }
02764 
02765     scGetSetStruct.hCard = hCard;
02766     scGetSetStruct.dwAttrId = dwAttrId;
02767     scGetSetStruct.cbAttrLen = *pcbAttrLen;
02768     scGetSetStruct.rv = SCARD_E_NO_SERVICE;
02769     memset(scGetSetStruct.pbAttr, 0, sizeof(scGetSetStruct.pbAttr));
02770     if (SCARD_SET_ATTRIB == command)
02771         memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
02772 
02773     rv = WrapSHMWrite(command,
02774         psContextMap[dwContextIndex].dwClientID, sizeof(scGetSetStruct),
02775         PCSCLITE_CLIENT_ATTEMPTS, &scGetSetStruct);
02776 
02777     if (rv == -1)
02778     {
02779         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02780         return SCARD_E_NO_SERVICE;
02781     }
02782 
02783     /*
02784      * Read a message from the server
02785      */
02786     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
02787         PCSCLITE_CLIENT_ATTEMPTS);
02788 
02789     if (rv == -1)
02790     {
02791         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02792         return SCARD_F_COMM_ERROR;
02793     }
02794 
02795     memcpy(&scGetSetStruct, &msgStruct.data, sizeof(scGetSetStruct));
02796 
02797     if ((SCARD_S_SUCCESS == scGetSetStruct.rv) && (SCARD_GET_ATTRIB == command))
02798     {
02799         /*
02800          * Copy and zero it so any secret information is not leaked
02801          */
02802         if (*pcbAttrLen < scGetSetStruct.cbAttrLen)
02803         {
02804             scGetSetStruct.cbAttrLen = *pcbAttrLen;
02805             scGetSetStruct.rv = SCARD_E_INSUFFICIENT_BUFFER;
02806         }
02807         else
02808             *pcbAttrLen = scGetSetStruct.cbAttrLen;
02809 
02810         if (pbAttr)
02811             memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen);
02812 
02813         memset(scGetSetStruct.pbAttr, 0x00, sizeof(scGetSetStruct.pbAttr));
02814     }
02815 
02816     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02817 
02818     return scGetSetStruct.rv;
02819 }
02820 
02879 LONG SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci,
02880     LPCBYTE pbSendBuffer, DWORD cbSendLength,
02881     LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer,
02882     LPDWORD pcbRecvLength)
02883 {
02884     LONG rv;
02885     int i;
02886     DWORD dwContextIndex, dwChannelIndex;
02887 
02888     PROFILE_START
02889 
02890     if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
02891             pcbRecvLength == NULL || pioSendPci == NULL)
02892         return SCARD_E_INVALID_PARAMETER;
02893 
02894     rv = SCardCheckDaemonAvailability();
02895     if (rv != SCARD_S_SUCCESS)
02896         return rv;
02897 
02898     /*
02899      * Make sure this handle has been opened
02900      */
02901     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02902     if (rv == -1)
02903     {
02904         *pcbRecvLength = 0;
02905         return SCARD_E_INVALID_HANDLE;
02906     }
02907 
02908     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
02909 
02910     /* check the handle is still valid */
02911     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02912     if (rv == -1)
02913         /* the handle is now invalid
02914          * -> another thread may have called SCardReleaseContext
02915          * -> so the mMutex has been unlocked */
02916         return SCARD_E_INVALID_HANDLE;
02917 
02918     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02919     {
02920         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02921 
02922         /* by default r == NULL */
02923         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02924             break;
02925     }
02926 
02927     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02928     {
02929         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02930         return SCARD_E_READER_UNAVAILABLE;
02931     }
02932 
02933     if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
02934         || (*pcbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
02935     {
02936         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02937         return SCARD_E_INSUFFICIENT_BUFFER;
02938     }
02939 
02940     if ((cbSendLength > MAX_BUFFER_SIZE) || (*pcbRecvLength > MAX_BUFFER_SIZE))
02941     {
02942         /* extended APDU */
02943         unsigned char buffer[sizeof(sharedSegmentMsg) + MAX_BUFFER_SIZE_EXTENDED];
02944         transmit_struct_extended *scTransmitStructExtended = (transmit_struct_extended *)buffer;
02945         sharedSegmentMsg *pmsgStruct = (psharedSegmentMsg)buffer;
02946 
02947         scTransmitStructExtended->hCard = hCard;
02948         scTransmitStructExtended->cbSendLength = cbSendLength;
02949         scTransmitStructExtended->pcbRecvLength = *pcbRecvLength;
02950         /* The size of data to send is the size of
02951          * struct control_struct_extended WITHOUT the data[] field
02952          * plus the effective data[] size
02953          */
02954         scTransmitStructExtended->size = sizeof(*scTransmitStructExtended)
02955             - (sizeof(transmit_struct_extended) - offsetof(transmit_struct_extended, data))
02956             + cbSendLength;
02957         scTransmitStructExtended->pioSendPciProtocol = pioSendPci->dwProtocol;
02958         scTransmitStructExtended->pioSendPciLength = pioSendPci->cbPciLength;
02959         memcpy(scTransmitStructExtended->data, pbSendBuffer, cbSendLength);
02960         scTransmitStructExtended->rv = SCARD_S_SUCCESS;
02961 
02962         if (pioRecvPci)
02963         {
02964             scTransmitStructExtended->pioRecvPciProtocol = pioRecvPci->dwProtocol;
02965             scTransmitStructExtended->pioRecvPciLength = pioRecvPci->cbPciLength;
02966         }
02967         else
02968         {
02969             scTransmitStructExtended->pioRecvPciProtocol = SCARD_PROTOCOL_ANY;
02970             scTransmitStructExtended->pioRecvPciLength = sizeof(SCARD_IO_REQUEST);
02971         }
02972 
02973         rv = WrapSHMWrite(SCARD_TRANSMIT_EXTENDED,
02974             psContextMap[dwContextIndex].dwClientID,
02975             scTransmitStructExtended->size,
02976             PCSCLITE_CLIENT_ATTEMPTS, buffer);
02977 
02978         if (rv == -1)
02979         {
02980             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02981             return SCARD_E_NO_SERVICE;
02982         }
02983 
02984         /*
02985          * Read a message from the server
02986          */
02987         /* read the first block */
02988         rv = SHMMessageReceive(buffer, sizeof(sharedSegmentMsg), psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
02989         if (rv == -1)
02990         {
02991             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02992             return SCARD_F_COMM_ERROR;
02993         }
02994 
02995         /* we receive a sharedSegmentMsg and not a transmit_struct_extended */
02996         scTransmitStructExtended = (transmit_struct_extended *)&(pmsgStruct -> data);
02997 
02998         /* a second block is present */
02999         if (scTransmitStructExtended->size > PCSCLITE_MAX_MESSAGE_SIZE)
03000         {
03001             rv = SHMMessageReceive(buffer + sizeof(sharedSegmentMsg),
03002                 scTransmitStructExtended->size-PCSCLITE_MAX_MESSAGE_SIZE,
03003                 psContextMap[dwContextIndex].dwClientID,
03004                 PCSCLITE_CLIENT_ATTEMPTS);
03005             if (rv == -1)
03006             {
03007                 (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03008                 return SCARD_F_COMM_ERROR;
03009             }
03010         }
03011 
03012         if (scTransmitStructExtended -> rv == SCARD_S_SUCCESS)
03013         {
03014             /*
03015              * Copy and zero it so any secret information is not leaked
03016              */
03017             memcpy(pbRecvBuffer, scTransmitStructExtended -> data,
03018                 scTransmitStructExtended -> pcbRecvLength);
03019             memset(scTransmitStructExtended -> data, 0x00,
03020                 scTransmitStructExtended -> pcbRecvLength);
03021 
03022             if (pioRecvPci)
03023             {
03024                 pioRecvPci->dwProtocol = scTransmitStructExtended->pioRecvPciProtocol;
03025                 pioRecvPci->cbPciLength = scTransmitStructExtended->pioRecvPciLength;
03026             }
03027         }
03028 
03029         *pcbRecvLength = scTransmitStructExtended -> pcbRecvLength;
03030         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03031 
03032         rv = scTransmitStructExtended -> rv;
03033     }
03034     else
03035     {
03036         /* short APDU */
03037         transmit_struct scTransmitStruct;
03038         sharedSegmentMsg msgStruct;
03039 
03040         scTransmitStruct.hCard = hCard;
03041         scTransmitStruct.cbSendLength = cbSendLength;
03042         scTransmitStruct.pcbRecvLength = *pcbRecvLength;
03043         scTransmitStruct.pioSendPciProtocol = pioSendPci->dwProtocol;
03044         scTransmitStruct.pioSendPciLength = pioSendPci->cbPciLength;
03045         memcpy(scTransmitStruct.pbSendBuffer, pbSendBuffer, cbSendLength);
03046         memset(scTransmitStruct.pbSendBuffer+cbSendLength, 0, sizeof(scTransmitStruct.pbSendBuffer)-cbSendLength);
03047         memset(scTransmitStruct.pbRecvBuffer, 0, sizeof(scTransmitStruct.pbRecvBuffer));
03048         scTransmitStruct.rv = SCARD_S_SUCCESS;
03049 
03050         if (pioRecvPci)
03051         {
03052             scTransmitStruct.pioRecvPciProtocol = pioRecvPci->dwProtocol;
03053             scTransmitStruct.pioRecvPciLength = pioRecvPci->cbPciLength;
03054         }
03055         else
03056         {
03057             scTransmitStruct.pioRecvPciProtocol = SCARD_PROTOCOL_ANY;
03058             scTransmitStruct.pioRecvPciLength = sizeof(SCARD_IO_REQUEST);
03059         }
03060 
03061         rv = WrapSHMWrite(SCARD_TRANSMIT,
03062             psContextMap[dwContextIndex].dwClientID, sizeof(scTransmitStruct),
03063             PCSCLITE_CLIENT_ATTEMPTS, (void *) &scTransmitStruct);
03064 
03065         if (rv == -1)
03066         {
03067             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03068             return SCARD_E_NO_SERVICE;
03069         }
03070 
03071         /*
03072          * Read a message from the server
03073          */
03074         rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
03075             PCSCLITE_CLIENT_ATTEMPTS);
03076 
03077         memcpy(&scTransmitStruct, &msgStruct.data, sizeof(scTransmitStruct));
03078 
03079         if (rv == -1)
03080         {
03081             (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03082             return SCARD_F_COMM_ERROR;
03083         }
03084 
03085         /*
03086          * Zero it and free it so any secret information cannot be leaked
03087          */
03088         memset(scTransmitStruct.pbSendBuffer, 0x00, cbSendLength);
03089 
03090         if (scTransmitStruct.rv == SCARD_S_SUCCESS)
03091         {
03092             /*
03093              * Copy and zero it so any secret information is not leaked
03094              */
03095             memcpy(pbRecvBuffer, scTransmitStruct.pbRecvBuffer,
03096                 scTransmitStruct.pcbRecvLength);
03097             memset(scTransmitStruct.pbRecvBuffer, 0x00,
03098                 scTransmitStruct.pcbRecvLength);
03099 
03100             if (pioRecvPci)
03101             {
03102                 pioRecvPci->dwProtocol = scTransmitStruct.pioRecvPciProtocol;
03103                 pioRecvPci->cbPciLength = scTransmitStruct.pioRecvPciLength;
03104             }
03105         }
03106 
03107         *pcbRecvLength = scTransmitStruct.pcbRecvLength;
03108         (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03109 
03110         rv = scTransmitStruct.rv;
03111     }
03112 
03113     PROFILE_END(rv)
03114 
03115     return rv;
03116 }
03117 
03166 LONG SCardListReaders(SCARDCONTEXT hContext, /*@unused@*/ LPCSTR mszGroups,
03167     LPSTR mszReaders, LPDWORD pcchReaders)
03168 {
03169     DWORD dwReadersLen;
03170     int i;
03171     LONG dwContextIndex;
03172     LONG rv = SCARD_S_SUCCESS;
03173     char *buf = NULL;
03174 
03175     (void)mszGroups;
03176     PROFILE_START
03177 
03178     /*
03179      * Check for NULL parameters
03180      */
03181     if (pcchReaders == NULL)
03182         return SCARD_E_INVALID_PARAMETER;
03183 
03184     rv = SCardCheckDaemonAvailability();
03185     if (rv != SCARD_S_SUCCESS)
03186         return rv;
03187 
03188     /*
03189      * Make sure this context has been opened
03190      */
03191     dwContextIndex = SCardGetContextIndice(hContext);
03192     if (dwContextIndex == -1)
03193         return SCARD_E_INVALID_HANDLE;
03194 
03195     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
03196 
03197     /* check the context is still opened */
03198     dwContextIndex = SCardGetContextIndice(hContext);
03199     if (dwContextIndex == -1)
03200         /* the context is now invalid
03201          * -> another thread may have called SCardReleaseContext
03202          * -> so the mMutex has been unlocked */
03203         return SCARD_E_INVALID_HANDLE;
03204 
03205     dwReadersLen = 0;
03206     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
03207         if ((readerStates[i])->readerID != 0)
03208             dwReadersLen += strlen((readerStates[i])->readerName) + 1;
03209 
03210     /* for the last NULL byte */
03211     dwReadersLen += 1;
03212 
03213     if (1 == dwReadersLen)
03214     {
03215         rv = SCARD_E_NO_READERS_AVAILABLE;
03216         goto end;
03217     }
03218 
03219     if (SCARD_AUTOALLOCATE == *pcchReaders)
03220     {
03221         buf = malloc(dwReadersLen);
03222         if (NULL == buf)
03223         {
03224             rv = SCARD_E_NO_MEMORY;
03225             goto end;
03226         }
03227         if (NULL == mszReaders)
03228         {
03229             rv = SCARD_E_INVALID_PARAMETER;
03230             goto end;
03231         }
03232         *(char **)mszReaders = buf;
03233     }
03234     else
03235     {
03236         buf = mszReaders;
03237 
03238         /* not enough place to store the reader names */
03239         if ((NULL != mszReaders) && (*pcchReaders < dwReadersLen))
03240         {
03241             rv = SCARD_E_INSUFFICIENT_BUFFER;
03242             goto end;
03243         }
03244     }
03245 
03246     if (mszReaders == NULL) /* text array not allocated */
03247         goto end;
03248 
03249     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
03250     {
03251         if ((readerStates[i])->readerID != 0)
03252         {
03253             /*
03254              * Build the multi-string
03255              */
03256             strcpy(buf, (readerStates[i])->readerName);
03257             buf += strlen((readerStates[i])->readerName)+1;
03258         }
03259     }
03260     *buf = '\0';    /* Add the last null */
03261 
03262 end:
03263     /* set the reader names length */
03264     *pcchReaders = dwReadersLen;
03265 
03266     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03267 
03268     PROFILE_END(rv)
03269 
03270     return rv;
03271 }
03272 
03285 LONG SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)
03286 {
03287     LONG rv = SCARD_S_SUCCESS;
03288     LONG dwContextIndex;
03289 
03290     PROFILE_START
03291 
03292     rv = SCardCheckDaemonAvailability();
03293     if (rv != SCARD_S_SUCCESS)
03294         return rv;
03295 
03296     /*
03297      * Make sure this context has been opened
03298      */
03299     dwContextIndex = SCardGetContextIndice(hContext);
03300     if (dwContextIndex == -1)
03301         return SCARD_E_INVALID_HANDLE;
03302 
03303     free((void *)pvMem);
03304 
03305     PROFILE_END(rv)
03306 
03307     return rv;
03308 }
03309 
03359 LONG SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups,
03360     LPDWORD pcchGroups)
03361 {
03362     LONG rv = SCARD_S_SUCCESS;
03363     LONG dwContextIndex;
03364     char *buf = NULL;
03365 
03366     PROFILE_START
03367 
03368     /* Multi-string with two trailing \0 */
03369     const char ReaderGroup[] = "SCard$DefaultReaders\0";
03370     const int dwGroups = sizeof(ReaderGroup);
03371 
03372     rv = SCardCheckDaemonAvailability();
03373     if (rv != SCARD_S_SUCCESS)
03374         return rv;
03375 
03376     /*
03377      * Make sure this context has been opened
03378      */
03379     dwContextIndex = SCardGetContextIndice(hContext);
03380     if (dwContextIndex == -1)
03381         return SCARD_E_INVALID_HANDLE;
03382 
03383     (void)SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
03384 
03385     /* check the context is still opened */
03386     dwContextIndex = SCardGetContextIndice(hContext);
03387     if (dwContextIndex == -1)
03388         /* the context is now invalid
03389          * -> another thread may have called SCardReleaseContext
03390          * -> so the mMutex has been unlocked */
03391         return SCARD_E_INVALID_HANDLE;
03392 
03393     if (SCARD_AUTOALLOCATE == *pcchGroups)
03394     {
03395         buf = malloc(dwGroups);
03396         if (NULL == buf)
03397         {
03398             rv = SCARD_E_NO_MEMORY;
03399             goto end;
03400         }
03401         if (NULL == mszGroups)
03402         {
03403             rv = SCARD_E_INVALID_PARAMETER;
03404             goto end;
03405         }
03406         *(char **)mszGroups = buf;
03407     }
03408     else
03409     {
03410         buf = mszGroups;
03411 
03412         if ((NULL != mszGroups) && (*pcchGroups < dwGroups))
03413         {
03414             rv = SCARD_E_INSUFFICIENT_BUFFER;
03415             goto end;
03416         }
03417     }
03418 
03419     if (buf)
03420         memcpy(buf, ReaderGroup, dwGroups);
03421 
03422 end:
03423     *pcchGroups = dwGroups;
03424 
03425     (void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03426 
03427     PROFILE_END(rv)
03428 
03429     return rv;
03430 }
03431 
03459 LONG SCardCancel(SCARDCONTEXT hContext)
03460 {
03461     LONG dwContextIndex;
03462     LONG rv = SCARD_S_SUCCESS;
03463 
03464     PROFILE_START
03465 
03466     dwContextIndex = SCardGetContextIndice(hContext);
03467     if (dwContextIndex == -1)
03468         return SCARD_E_INVALID_HANDLE;
03469 
03470     /*
03471      * Set the block status for this Context so blocking calls will
03472      * complete
03473      */
03474     psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_RESUME;
03475 
03476     if (StatSynchronizeContext(hContext))
03477         rv = SCARD_F_INTERNAL_ERROR;
03478 
03479     PROFILE_END(rv)
03480 
03481     return rv;
03482 }
03483 
03507 LONG SCardIsValidContext(SCARDCONTEXT hContext)
03508 {
03509     LONG rv;
03510     LONG dwContextIndex;
03511 
03512     PROFILE_START
03513 
03514     rv = SCARD_S_SUCCESS;
03515 
03516     /* Check if the _same_ server is running */
03517     rv = SCardCheckDaemonAvailability();
03518     if (rv != SCARD_S_SUCCESS)
03519         return rv;
03520 
03521     /*
03522      * Make sure this context has been opened
03523      */
03524     dwContextIndex = SCardGetContextIndice(hContext);
03525     if (dwContextIndex == -1)
03526         rv = SCARD_E_INVALID_HANDLE;
03527 
03528     PROFILE_END(rv)
03529 
03530     return rv;
03531 }
03532 
03549 static LONG SCardAddContext(SCARDCONTEXT hContext, DWORD dwClientID)
03550 {
03551     int i;
03552 
03553     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03554     {
03555         if (psContextMap[i].hContext == 0)
03556         {
03557             psContextMap[i].hContext = hContext;
03558             psContextMap[i].dwClientID = dwClientID;
03559             psContextMap[i].contextBlockStatus = BLOCK_STATUS_RESUME;
03560             psContextMap[i].mMutex = malloc(sizeof(PCSCLITE_MUTEX));
03561             (void)SYS_MutexInit(psContextMap[i].mMutex);
03562             return SCARD_S_SUCCESS;
03563         }
03564     }
03565 
03566     return SCARD_E_NO_MEMORY;
03567 }
03568 
03581 static LONG SCardGetContextIndice(SCARDCONTEXT hContext)
03582 {
03583     LONG rv;
03584 
03585     (void)SCardLockThread();
03586     rv = SCardGetContextIndiceTH(hContext);
03587     (void)SCardUnlockThread();
03588 
03589     return rv;
03590 }
03591 
03604 static LONG SCardGetContextIndiceTH(SCARDCONTEXT hContext)
03605 {
03606     int i;
03607 
03608     /*
03609      * Find this context and return its spot in the array
03610      */
03611     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03612     {
03613         if ((hContext == psContextMap[i].hContext) && (hContext != 0))
03614             return i;
03615     }
03616 
03617     return -1;
03618 }
03619 
03629 static LONG SCardRemoveContext(SCARDCONTEXT hContext)
03630 {
03631     LONG  retIndice;
03632 
03633     retIndice = SCardGetContextIndiceTH(hContext);
03634 
03635     if (retIndice == -1)
03636         return SCARD_E_INVALID_HANDLE;
03637     else
03638         return SCardCleanContext(retIndice);
03639 }
03640 
03641 static LONG SCardCleanContext(LONG indice)
03642 {
03643     int i;
03644 
03645     psContextMap[indice].hContext = 0;
03646     (void)SHMClientCloseSession(psContextMap[indice].dwClientID);
03647     psContextMap[indice].dwClientID = 0;
03648     free(psContextMap[indice].mMutex);
03649     psContextMap[indice].mMutex = NULL;
03650     psContextMap[indice].contextBlockStatus = BLOCK_STATUS_RESUME;
03651 
03652     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03653     {
03654         /*
03655          * Reset the \c hCard structs to zero
03656          */
03657         psContextMap[indice].psChannelMap[i].hCard = 0;
03658         free(psContextMap[indice].psChannelMap[i].readerName);
03659         psContextMap[indice].psChannelMap[i].readerName = NULL;
03660     }
03661 
03662     return SCARD_S_SUCCESS;
03663 }
03664 
03665 /*
03666  * Functions for managing hCard values returned from SCardConnect.
03667  */
03668 
03669 static LONG SCardAddHandle(SCARDHANDLE hCard, DWORD dwContextIndex,
03670     LPCSTR readerName)
03671 {
03672     int i;
03673 
03674     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03675     {
03676         if (psContextMap[dwContextIndex].psChannelMap[i].hCard == 0)
03677         {
03678             psContextMap[dwContextIndex].psChannelMap[i].hCard = hCard;
03679             psContextMap[dwContextIndex].psChannelMap[i].readerName = strdup(readerName);
03680             return SCARD_S_SUCCESS;
03681         }
03682     }
03683 
03684     return SCARD_E_NO_MEMORY;
03685 }
03686 
03687 static LONG SCardRemoveHandle(SCARDHANDLE hCard)
03688 {
03689     DWORD dwContextIndice, dwChannelIndice;
03690     LONG rv;
03691 
03692     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndice, &dwChannelIndice);
03693     if (rv == -1)
03694         return SCARD_E_INVALID_HANDLE;
03695     else
03696     {
03697         psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].hCard = 0;
03698         free(psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName);
03699         psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName = NULL;
03700         return SCARD_S_SUCCESS;
03701     }
03702 }
03703 
03704 static LONG SCardGetIndicesFromHandle(SCARDHANDLE hCard,
03705     PDWORD pdwContextIndice, PDWORD pdwChannelIndice)
03706 {
03707     LONG rv;
03708 
03709     if (0 == hCard)
03710         return -1;
03711 
03712     (void)SCardLockThread();
03713     rv = SCardGetIndicesFromHandleTH(hCard, pdwContextIndice, pdwChannelIndice);
03714     (void)SCardUnlockThread();
03715 
03716     return rv;
03717 }
03718 
03719 static LONG SCardGetIndicesFromHandleTH(SCARDHANDLE hCard,
03720     PDWORD pdwContextIndice, PDWORD pdwChannelIndice)
03721 {
03722     int i;
03723 
03724     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03725     {
03726         if (psContextMap[i].hContext != 0)
03727         {
03728             int j;
03729 
03730             for (j = 0; j < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; j++)
03731             {
03732                 if (psContextMap[i].psChannelMap[j].hCard == hCard)
03733                 {
03734                     *pdwContextIndice = i;
03735                     *pdwChannelIndice = j;
03736                     return SCARD_S_SUCCESS;
03737                 }
03738             }
03739 
03740         }
03741     }
03742 
03743     return -1;
03744 }
03745 
03754 LONG SCardCheckDaemonAvailability(void)
03755 {
03756     LONG rv;
03757     struct stat statBuffer;
03758     int need_restart = 0;
03759 
03760     rv = SYS_Stat(PCSCLITE_PUBSHM_FILE, &statBuffer);
03761 
03762     if (rv != 0)
03763     {
03764         Log2(PCSC_LOG_INFO, "PCSC Not Running: " PCSCLITE_PUBSHM_FILE ": %s",
03765             strerror(errno));
03766         return SCARD_E_NO_SERVICE;
03767     }
03768 
03769     /* when the _first_ reader is connected the ctime changes
03770      * I don't know why yet */
03771     if (daemon_ctime && statBuffer.st_ctime > daemon_ctime)
03772     {
03773         /* so we also check the daemon pid to be sure it is a new pcscd */
03774         if (GetDaemonPid() != daemon_pid)
03775         {
03776             Log1(PCSC_LOG_INFO, "PCSC restarted");
03777             need_restart = 1;
03778         }
03779     }
03780 
03781     /* after fork() need to restart */
03782     if (client_pid && client_pid != getpid())
03783     {
03784         Log1(PCSC_LOG_INFO, "Client forked");
03785         need_restart = 1;
03786     }
03787 
03788     if (need_restart)
03789     {
03790         int i;
03791 
03792         /* invalid all handles */
03793         (void)SCardLockThread();
03794 
03795         for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03796             if (psContextMap[i].hContext)
03797                 (void)SCardCleanContext(i);
03798 
03799         (void)SCardUnlockThread();
03800 
03801         /* reset pcscd status */
03802         daemon_ctime = 0;
03803         client_pid = 0;
03804 
03805         /* reset the lib */
03806         SCardUnload();
03807 
03808         return SCARD_E_INVALID_HANDLE;
03809     }
03810 
03811     daemon_ctime = statBuffer.st_ctime;
03812     daemon_pid = GetDaemonPid();
03813     client_pid = getpid();
03814 
03815     return SCARD_S_SUCCESS;
03816 }
03817 
03824 #ifdef __SUNPRO_C
03825 #pragma fini (SCardUnload)
03826 #endif
03827 
03828 void DESTRUCTOR SCardUnload(void)
03829 {
03830     int i;
03831 
03832     if (!isExecuted)
03833         return;
03834 
03835     /* unmap public shared file from memory */
03836     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03837     {
03838         if (readerStates[i] != NULL)
03839         {
03840             SYS_PublicMemoryUnmap(readerStates[i], sizeof(READER_STATE));
03841             readerStates[i] = NULL;
03842         }
03843     }
03844 
03845     (void)SYS_CloseFile(mapAddr);
03846     isExecuted = 0;
03847 }
03848 

Generated on Wed Jun 17 07:12:38 2009 for pcsc-lite by  doxygen 1.5.8