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 3020 2008-06-24 09:58:34Z 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 
00031 #include "misc.h"
00032 #include "pcscd.h"
00033 #include "winscard.h"
00034 #include "debug.h"
00035 #include "thread_generic.h"
00036 #include "strlcpycat.h"
00037 
00038 #include "readerfactory.h"
00039 #include "eventhandler.h"
00040 #include "sys_generic.h"
00041 #include "winscard_msg.h"
00042 #include "utils.h"
00043 
00045 #define SCARD_PROTOCOL_ANY_OLD  0x1000
00046 
00047 #ifndef TRUE
00048 #define TRUE 1
00049 #define FALSE 0
00050 #endif
00051 
00052 #undef DO_PROFILE
00053 #ifdef DO_PROFILE
00054 
00055 #define PROFILE_FILE "/tmp/pcsc_profile"
00056 #include <stdio.h>
00057 #include <sys/time.h>
00058 
00059 struct timeval profile_time_start;
00060 FILE *fd;
00061 char profile_tty;
00062 char fct_name[100];
00063 
00064 #define PROFILE_START profile_start(__FUNCTION__);
00065 #define PROFILE_END(rv) profile_end(__FUNCTION__, rv);
00066 
00067 static void profile_start(const char *f)
00068 {
00069     static char initialized = FALSE;
00070 
00071     if (!initialized)
00072     {
00073         char filename[80];
00074 
00075         initialized = TRUE;
00076         sprintf(filename, "%s-%d", PROFILE_FILE, getuid());
00077         fd = fopen(filename, "a+");
00078         if (NULL == fd)
00079         {
00080             fprintf(stderr, "\33[01;31mCan't open %s: %s\33[0m\n",
00081                 PROFILE_FILE, strerror(errno));
00082             exit(-1);
00083         }
00084         fprintf(fd, "\nStart a new profile\n");
00085 
00086         if (isatty(fileno(stderr)))
00087             profile_tty = TRUE;
00088         else
00089             profile_tty = FALSE;
00090     }
00091 
00092     /* PROFILE_END was not called before? */
00093     if (profile_tty && fct_name[0])
00094         printf("\33[01;34m WARNING: %s starts before %s finishes\33[0m\n",
00095             f, fct_name);
00096 
00097     strlcpy(fct_name, f, sizeof(fct_name));
00098 
00099     gettimeofday(&profile_time_start, NULL);
00100 } /* profile_start */
00101 
00102 /* r = a - b */
00103 static long int time_sub(struct timeval *a, struct timeval *b)
00104 {
00105     struct timeval r;
00106     r.tv_sec = a -> tv_sec - b -> tv_sec;
00107     r.tv_usec = a -> tv_usec - b -> tv_usec;
00108     if (r.tv_usec < 0)
00109     {
00110         r.tv_sec--;
00111         r.tv_usec += 1000000;
00112     }
00113 
00114     return r.tv_sec * 1000000 + r.tv_usec;
00115 } /* time_sub */
00116 
00117 
00118 static void profile_end(const char *f, LONG rv)
00119 {
00120     struct timeval profile_time_end;
00121     long d;
00122 
00123     gettimeofday(&profile_time_end, NULL);
00124     d = time_sub(&profile_time_end, &profile_time_start);
00125 
00126     if (profile_tty)
00127     {
00128         if (fct_name[0])
00129         {
00130             if (strncmp(fct_name, f, sizeof(fct_name)))
00131                 printf("\33[01;34m WARNING: %s ends before %s\33[0m\n",
00132                         f, fct_name);
00133         }
00134         else
00135             printf("\33[01;34m WARNING: %s ends but we lost its start\33[0m\n",
00136                 f);
00137 
00138         /* allow to detect missing PROFILE_END calls */
00139         fct_name[0] = '\0';
00140 
00141         if (rv != SCARD_S_SUCCESS)
00142             fprintf(stderr,
00143                 "\33[01;31mRESULT %s \33[35m%ld \33[34m0x%08lX %s\33[0m\n",
00144                 f, d, rv, pcsc_stringify_error(rv));
00145         else
00146             fprintf(stderr, "\33[01;31mRESULT %s \33[35m%ld\33[0m\n", f, d);
00147     }
00148     fprintf(fd, "%s %ld\n", f, d);
00149     fflush(fd);
00150 } /* profile_end */
00151 
00152 #else
00153 #define PROFILE_START
00154 #define PROFILE_END(rv)
00155 #endif
00156 
00161 struct _psChannelMap
00162 {
00163     SCARDHANDLE hCard;
00164     LPSTR readerName;
00165 };
00166 
00167 typedef struct _psChannelMap CHANNEL_MAP, *PCHANNEL_MAP;
00168 
00174 static struct _psContextMap
00175 {
00176     DWORD dwClientID;               
00177     SCARDCONTEXT hContext;          
00178     DWORD contextBlockStatus;
00179     PCSCLITE_MUTEX_T mMutex;        
00180     CHANNEL_MAP psChannelMap[PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS];
00181 } psContextMap[PCSCLITE_MAX_APPLICATION_CONTEXTS];
00182 
00186 static short isExecuted = 0;
00187 
00188 
00192 static time_t daemon_ctime = 0;
00193 static pid_t daemon_pid = 0;
00198 static pid_t client_pid = 0;
00199 
00205 static int mapAddr = 0;
00206 
00211 static PCSCLITE_MUTEX clientMutex = PTHREAD_MUTEX_INITIALIZER;
00212 
00219 static PREADER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS];
00220 
00221 PCSC_API SCARD_IO_REQUEST g_rgSCardT0Pci = { SCARD_PROTOCOL_T0, 8 };
00222 PCSC_API SCARD_IO_REQUEST g_rgSCardT1Pci = { SCARD_PROTOCOL_T1, 8 };
00223 PCSC_API SCARD_IO_REQUEST g_rgSCardRawPci = { SCARD_PROTOCOL_RAW, 8 };
00224 
00225 
00226 static LONG SCardAddContext(SCARDCONTEXT, DWORD);
00227 static LONG SCardGetContextIndice(SCARDCONTEXT);
00228 static LONG SCardGetContextIndiceTH(SCARDCONTEXT);
00229 static LONG SCardRemoveContext(SCARDCONTEXT);
00230 static LONG SCardCleanContext(LONG indice);
00231 
00232 static LONG SCardAddHandle(SCARDHANDLE, DWORD, LPCSTR);
00233 static LONG SCardGetIndicesFromHandle(SCARDHANDLE, PDWORD, PDWORD);
00234 static LONG SCardGetIndicesFromHandleTH(SCARDHANDLE, PDWORD, PDWORD);
00235 static LONG SCardRemoveHandle(SCARDHANDLE);
00236 
00237 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
00238     LPBYTE pbAttr, LPDWORD pcbAttrLen);
00239 
00240 void DESTRUCTOR SCardUnload(void);
00241 
00242 /*
00243  * Thread safety functions
00244  */
00251 inline static LONG SCardLockThread(void)
00252 {
00253     return SYS_MutexLock(&clientMutex);
00254 }
00255 
00261 inline static LONG SCardUnlockThread(void)
00262 {
00263     return SYS_MutexUnLock(&clientMutex);
00264 }
00265 
00266 static LONG SCardEstablishContextTH(DWORD, LPCVOID, LPCVOID, LPSCARDCONTEXT);
00267 
00302 LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
00303     LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
00304 {
00305     LONG rv;
00306 
00307     PROFILE_START
00308 
00309     /* Check if the server is running */
00310     rv = SCardCheckDaemonAvailability();
00311     if (SCARD_E_INVALID_HANDLE == rv)
00312         /* we reconnected to a daemon or we got called from a forked child */
00313         rv = SCardCheckDaemonAvailability();
00314 
00315     if (rv != SCARD_S_SUCCESS)
00316         return rv;
00317 
00318     SCardLockThread();
00319     rv = SCardEstablishContextTH(dwScope, pvReserved1,
00320         pvReserved2, phContext);
00321     SCardUnlockThread();
00322 
00323     PROFILE_END(rv)
00324 
00325     return rv;
00326 }
00327 
00354 static LONG SCardEstablishContextTH(DWORD dwScope, LPCVOID pvReserved1,
00355     LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
00356 {
00357     LONG rv;
00358     int i;
00359     establish_struct scEstablishStruct;
00360     sharedSegmentMsg msgStruct;
00361     uint32_t dwClientID = 0;
00362 
00363     if (phContext == NULL)
00364         return SCARD_E_INVALID_PARAMETER;
00365     else
00366         *phContext = 0;
00367 
00368     /*
00369      * Do this only once:
00370      * - Initialize debug of need.
00371      * - Set up the memory mapped structures for reader states.
00372      * - Allocate each reader structure.
00373      * - Initialize context struct.
00374      */
00375     if (isExecuted == 0)
00376     {
00377         int pageSize;
00378 
00379         /*
00380          * Do any system initilization here
00381          */
00382         SYS_Initialize();
00383 
00384         /*
00385          * Set up the memory mapped reader stats structures
00386          */
00387         mapAddr = SYS_OpenFile(PCSCLITE_PUBSHM_FILE, O_RDONLY, 0);
00388         if (mapAddr < 0)
00389         {
00390             Log3(PCSC_LOG_CRITICAL, "Cannot open public shared file %s: %s",
00391                 PCSCLITE_PUBSHM_FILE, strerror(errno));
00392             return SCARD_E_NO_SERVICE;
00393         }
00394 
00395         /* close on exec so that child processes do not inherits the file
00396          * descriptor. The child process will call SCardEstablishContext()
00397          * if needed. */
00398         fcntl(mapAddr, F_SETFD, FD_CLOEXEC);
00399 
00400         pageSize = SYS_GetPageSize();
00401 
00402         /*
00403          * Allocate each reader structure in the memory map
00404          */
00405         for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
00406         {
00407             readerStates[i] =
00408                 (PREADER_STATE)SYS_PublicMemoryMap(sizeof(READER_STATE),
00409                 mapAddr, (i * pageSize));
00410             if (readerStates[i] == NULL)
00411             {
00412                 Log2(PCSC_LOG_CRITICAL, "Cannot public memory map: %s",
00413                     strerror(errno));
00414                 SYS_CloseFile(mapAddr); /* Close the memory map file */
00415                 return SCARD_F_INTERNAL_ERROR;
00416             }
00417         }
00418 
00419         /*
00420          * Initializes the application contexts and all channels for each one
00421          */
00422         for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
00423         {
00424             int j;
00425 
00426             /*
00427              * Initially set the context struct to zero
00428              */
00429             psContextMap[i].dwClientID = 0;
00430             psContextMap[i].hContext = 0;
00431             psContextMap[i].contextBlockStatus = BLOCK_STATUS_RESUME;
00432             psContextMap[i].mMutex = NULL;
00433 
00434             for (j = 0; j < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; j++)
00435             {
00436                 /*
00437                  * Initially set the hcard structs to zero
00438                  */
00439                 psContextMap[i].psChannelMap[j].hCard = 0;
00440                 psContextMap[i].psChannelMap[j].readerName = NULL;
00441             }
00442         }
00443 
00444     }
00445 
00446     /*
00447      * Is there a free slot for this connection ?
00448      */
00449 
00450     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
00451     {
00452         if (psContextMap[i].dwClientID == 0)
00453             break;
00454     }
00455 
00456     if (i == PCSCLITE_MAX_APPLICATION_CONTEXTS)
00457     {
00458         return SCARD_E_NO_MEMORY;
00459     }
00460 
00461     /* Establishes a connection to the server */
00462     if (SHMClientSetupSession(&dwClientID) != 0)
00463     {
00464         SYS_CloseFile(mapAddr);
00465         return SCARD_E_NO_SERVICE;
00466     }
00467 
00468     {   /* exchange client/server protocol versions */
00469         version_struct *veStr;
00470 
00471         memset(&msgStruct, 0, sizeof(msgStruct));
00472         msgStruct.mtype = CMD_VERSION;
00473         msgStruct.user_id = SYS_GetUID();
00474         msgStruct.group_id = SYS_GetGID();
00475         msgStruct.command = 0;
00476         msgStruct.date = time(NULL);
00477 
00478         veStr = (version_struct *) msgStruct.data;
00479         veStr->major = PROTOCOL_VERSION_MAJOR;
00480         veStr->minor = PROTOCOL_VERSION_MINOR;
00481 
00482         if (-1 == SHMMessageSend(&msgStruct, sizeof(msgStruct), dwClientID,
00483             PCSCLITE_MCLIENT_ATTEMPTS))
00484             return SCARD_E_NO_SERVICE;
00485 
00486         /*
00487          * Read a message from the server
00488          */
00489         if (-1 == SHMMessageReceive(&msgStruct, sizeof(msgStruct), dwClientID,
00490             PCSCLITE_CLIENT_ATTEMPTS))
00491         {
00492             Log1(PCSC_LOG_CRITICAL, "Your pcscd is too old and does not support CMD_VERSION");
00493             return SCARD_F_COMM_ERROR;
00494         }
00495 
00496         Log3(PCSC_LOG_INFO, "Server is protocol version %d:%d",
00497             veStr->major, veStr->minor);
00498 
00499         if (veStr->rv != SCARD_S_SUCCESS)
00500             return veStr->rv;
00501 
00502         isExecuted = 1;
00503     }
00504 
00505 
00506     /*
00507      * Try to establish an Application Context with the server
00508      */
00509     scEstablishStruct.dwScope = dwScope;
00510     scEstablishStruct.phContext = 0;
00511     scEstablishStruct.rv = SCARD_S_SUCCESS;
00512 
00513     rv = WrapSHMWrite(SCARD_ESTABLISH_CONTEXT, dwClientID,
00514         sizeof(scEstablishStruct), PCSCLITE_MCLIENT_ATTEMPTS,
00515         (void *) &scEstablishStruct);
00516 
00517     if (rv == -1)
00518         return SCARD_E_NO_SERVICE;
00519 
00520     /*
00521      * Read the response from the server
00522      */
00523     rv = SHMClientRead(&msgStruct, dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
00524 
00525     if (rv == -1)
00526         return SCARD_F_COMM_ERROR;
00527 
00528     memcpy(&scEstablishStruct, &msgStruct.data, sizeof(scEstablishStruct));
00529 
00530     if (scEstablishStruct.rv != SCARD_S_SUCCESS)
00531         return scEstablishStruct.rv;
00532 
00533     *phContext = scEstablishStruct.phContext;
00534 
00535     /*
00536      * Allocate the new hContext - if allocator full return an error
00537      */
00538     rv = SCardAddContext(*phContext, dwClientID);
00539 
00540     return rv;
00541 }
00542 
00565 LONG SCardReleaseContext(SCARDCONTEXT hContext)
00566 {
00567     LONG rv;
00568     release_struct scReleaseStruct;
00569     sharedSegmentMsg msgStruct;
00570     LONG dwContextIndex;
00571 
00572     PROFILE_START
00573 
00574     /*
00575      * Make sure this context has been opened
00576      * and get dwContextIndex
00577      */
00578     dwContextIndex = SCardGetContextIndice(hContext);
00579     if (dwContextIndex == -1)
00580         return SCARD_E_INVALID_HANDLE;
00581 
00582     rv = SCardCheckDaemonAvailability();
00583     if (rv != SCARD_S_SUCCESS)
00584     {
00585         /*
00586          * Remove the local context from the stack
00587          */
00588         SCardLockThread();
00589         SCardRemoveContext(hContext);
00590         SCardUnlockThread();
00591 
00592         return rv;
00593     }
00594 
00595     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
00596 
00597     /* check the context is still opened */
00598     dwContextIndex = SCardGetContextIndice(hContext);
00599     if (dwContextIndex == -1)
00600         /* the context is now invalid
00601          * -> another thread may have called SCardReleaseContext
00602          * -> so the mMutex has been unlocked */
00603         return SCARD_E_INVALID_HANDLE;
00604 
00605     scReleaseStruct.hContext = hContext;
00606     scReleaseStruct.rv = SCARD_S_SUCCESS;
00607 
00608     rv = WrapSHMWrite(SCARD_RELEASE_CONTEXT,
00609         psContextMap[dwContextIndex].dwClientID,
00610         sizeof(scReleaseStruct),
00611         PCSCLITE_MCLIENT_ATTEMPTS, (void *) &scReleaseStruct);
00612 
00613     if (rv == -1)
00614     {
00615         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00616         return SCARD_E_NO_SERVICE;
00617     }
00618 
00619     /*
00620      * Read a message from the server
00621      */
00622     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
00623         PCSCLITE_CLIENT_ATTEMPTS);
00624     memcpy(&scReleaseStruct, &msgStruct.data, sizeof(scReleaseStruct));
00625 
00626     if (rv == -1)
00627     {
00628         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00629         return SCARD_F_COMM_ERROR;
00630     }
00631 
00632     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00633 
00634     /*
00635      * Remove the local context from the stack
00636      */
00637     SCardLockThread();
00638     SCardRemoveContext(hContext);
00639     SCardUnlockThread();
00640 
00641     PROFILE_END(scReleaseStruct.rv)
00642 
00643     return scReleaseStruct.rv;
00644 }
00645 
00659 LONG SCardSetTimeout(SCARDCONTEXT hContext, DWORD dwTimeout)
00660 {
00661     /*
00662      * Deprecated
00663      */
00664 
00665     return SCARD_S_SUCCESS;
00666 }
00667 
00720 LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader,
00721     DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
00722     LPDWORD pdwActiveProtocol)
00723 {
00724     LONG rv;
00725     connect_struct scConnectStruct;
00726     sharedSegmentMsg msgStruct;
00727     LONG dwContextIndex;
00728 
00729     PROFILE_START
00730 
00731     /*
00732      * Check for NULL parameters
00733      */
00734     if (phCard == NULL || pdwActiveProtocol == NULL)
00735         return SCARD_E_INVALID_PARAMETER;
00736     else
00737         *phCard = 0;
00738 
00739     if (szReader == NULL)
00740         return SCARD_E_UNKNOWN_READER;
00741 
00742     /*
00743      * Check for uninitialized strings
00744      */
00745     if (strlen(szReader) > MAX_READERNAME)
00746         return SCARD_E_INVALID_VALUE;
00747 
00748     rv = SCardCheckDaemonAvailability();
00749     if (rv != SCARD_S_SUCCESS)
00750         return rv;
00751 
00752     /*
00753      * Make sure this context has been opened
00754      */
00755     dwContextIndex = SCardGetContextIndice(hContext);
00756     if (dwContextIndex == -1)
00757         return SCARD_E_INVALID_HANDLE;
00758 
00759     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
00760 
00761     /* check the context is still opened */
00762     dwContextIndex = SCardGetContextIndice(hContext);
00763     if (dwContextIndex == -1)
00764         /* the context is now invalid
00765          * -> another thread may have called SCardReleaseContext
00766          * -> so the mMutex has been unlocked */
00767         return SCARD_E_INVALID_HANDLE;
00768 
00769     strncpy(scConnectStruct.szReader, szReader, MAX_READERNAME);
00770 
00771     scConnectStruct.hContext = hContext;
00772     scConnectStruct.dwShareMode = dwShareMode;
00773     scConnectStruct.dwPreferredProtocols = dwPreferredProtocols;
00774     scConnectStruct.phCard = 0;
00775     scConnectStruct.pdwActiveProtocol = 0;
00776     scConnectStruct.rv = SCARD_S_SUCCESS;
00777 
00778     rv = WrapSHMWrite(SCARD_CONNECT, psContextMap[dwContextIndex].dwClientID,
00779         sizeof(scConnectStruct),
00780         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scConnectStruct);
00781 
00782     if (rv == -1)
00783     {
00784         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00785         return SCARD_E_NO_SERVICE;
00786     }
00787 
00788     /*
00789      * Read a message from the server
00790      */
00791     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
00792         PCSCLITE_CLIENT_ATTEMPTS);
00793 
00794     memcpy(&scConnectStruct, &msgStruct.data, sizeof(scConnectStruct));
00795 
00796     if (rv == -1)
00797     {
00798         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00799         return SCARD_F_COMM_ERROR;
00800     }
00801 
00802     *phCard = scConnectStruct.phCard;
00803     *pdwActiveProtocol = scConnectStruct.pdwActiveProtocol;
00804 
00805     if (scConnectStruct.rv == SCARD_S_SUCCESS)
00806     {
00807         /*
00808          * Keep track of the handle locally
00809          */
00810         rv = SCardAddHandle(*phCard, dwContextIndex, szReader);
00811         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00812 
00813         PROFILE_END(rv)
00814 
00815         return rv;
00816     }
00817 
00818     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00819 
00820     PROFILE_END(scConnectStruct.rv)
00821 
00822     return scConnectStruct.rv;
00823 }
00824 
00890 LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
00891     DWORD dwPreferredProtocols, DWORD dwInitialization,
00892     LPDWORD pdwActiveProtocol)
00893 {
00894     LONG rv;
00895     reconnect_struct scReconnectStruct;
00896     sharedSegmentMsg msgStruct;
00897     int i;
00898     DWORD dwContextIndex, dwChannelIndex;
00899 
00900     PROFILE_START
00901 
00902     if (pdwActiveProtocol == NULL)
00903         return SCARD_E_INVALID_PARAMETER;
00904 
00905     rv = SCardCheckDaemonAvailability();
00906     if (rv != SCARD_S_SUCCESS)
00907         return rv;
00908 
00909     /*
00910      * Make sure this handle has been opened
00911      */
00912     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
00913     if (rv == -1)
00914         return SCARD_E_INVALID_HANDLE;
00915 
00916     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
00917 
00918     /* check the handle is still valid */
00919     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
00920     if (rv == -1)
00921         /* the handle is now invalid
00922          * -> another thread may have called SCardReleaseContext
00923          * -> so the mMutex has been unlocked */
00924         return SCARD_E_INVALID_HANDLE;
00925 
00926     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
00927     {
00928         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
00929 
00930         /* by default r == NULL */
00931         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
00932             break;
00933     }
00934 
00935     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
00936     {
00937         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00938         return SCARD_E_READER_UNAVAILABLE;
00939     }
00940 
00941     do
00942     {
00943         scReconnectStruct.hCard = hCard;
00944         scReconnectStruct.dwShareMode = dwShareMode;
00945         scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
00946         scReconnectStruct.dwInitialization = dwInitialization;
00947         scReconnectStruct.pdwActiveProtocol = *pdwActiveProtocol;
00948         scReconnectStruct.rv = SCARD_S_SUCCESS;
00949 
00950         rv = WrapSHMWrite(SCARD_RECONNECT, psContextMap[dwContextIndex].dwClientID,
00951             sizeof(scReconnectStruct),
00952             PCSCLITE_CLIENT_ATTEMPTS, (void *) &scReconnectStruct);
00953 
00954         if (rv == -1)
00955         {
00956             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00957             return SCARD_E_NO_SERVICE;
00958         }
00959 
00960         /*
00961          * Read a message from the server
00962          */
00963         rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
00964             PCSCLITE_CLIENT_ATTEMPTS);
00965 
00966         memcpy(&scReconnectStruct, &msgStruct.data, sizeof(scReconnectStruct));
00967 
00968         if (rv == -1)
00969         {
00970             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00971             return SCARD_F_COMM_ERROR;
00972         }
00973     } while (SCARD_E_SHARING_VIOLATION == scReconnectStruct.rv);
00974 
00975     *pdwActiveProtocol = scReconnectStruct.pdwActiveProtocol;
00976 
00977     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
00978 
00979     PROFILE_END(scReconnectStruct.rv)
00980 
00981     return scReconnectStruct.rv;
00982 }
00983 
01015 LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
01016 {
01017     LONG rv;
01018     disconnect_struct scDisconnectStruct;
01019     sharedSegmentMsg msgStruct;
01020     DWORD dwContextIndex, dwChannelIndex;
01021 
01022     PROFILE_START
01023 
01024     rv = SCardCheckDaemonAvailability();
01025     if (rv != SCARD_S_SUCCESS)
01026         return rv;
01027 
01028     /*
01029      * Make sure this handle has been opened
01030      */
01031     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01032     if (rv == -1)
01033         return SCARD_E_INVALID_HANDLE;
01034 
01035     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01036 
01037     /* check the handle is still valid */
01038     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01039     if (rv == -1)
01040         /* the handle is now invalid
01041          * -> another thread may have called SCardReleaseContext
01042          * -> so the mMutex has been unlocked */
01043         return SCARD_E_INVALID_HANDLE;
01044 
01045     scDisconnectStruct.hCard = hCard;
01046     scDisconnectStruct.dwDisposition = dwDisposition;
01047     scDisconnectStruct.rv = SCARD_S_SUCCESS;
01048 
01049     rv = WrapSHMWrite(SCARD_DISCONNECT, psContextMap[dwContextIndex].dwClientID,
01050         sizeof(scDisconnectStruct),
01051         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scDisconnectStruct);
01052 
01053     if (rv == -1)
01054     {
01055         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01056         return SCARD_E_NO_SERVICE;
01057     }
01058 
01059     /*
01060      * Read a message from the server
01061      */
01062     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01063         PCSCLITE_CLIENT_ATTEMPTS);
01064 
01065     memcpy(&scDisconnectStruct, &msgStruct.data,
01066         sizeof(scDisconnectStruct));
01067 
01068     if (rv == -1)
01069     {
01070         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01071         return SCARD_F_COMM_ERROR;
01072     }
01073 
01074     SCardRemoveHandle(hCard);
01075 
01076     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01077 
01078     PROFILE_END(scDisconnectStruct.rv)
01079 
01080     return scDisconnectStruct.rv;
01081 }
01082 
01118 LONG SCardBeginTransaction(SCARDHANDLE hCard)
01119 {
01120 
01121     LONG rv;
01122     begin_struct scBeginStruct;
01123     int i;
01124     sharedSegmentMsg msgStruct;
01125     DWORD dwContextIndex, dwChannelIndex;
01126 
01127     PROFILE_START
01128 
01129     rv = SCardCheckDaemonAvailability();
01130     if (rv != SCARD_S_SUCCESS)
01131         return rv;
01132 
01133     /*
01134      * Make sure this handle has been opened
01135      */
01136     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01137     if (rv == -1)
01138         return SCARD_E_INVALID_HANDLE;
01139 
01140     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01141 
01142     /* check the handle is still valid */
01143     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01144     if (rv == -1)
01145         /* the handle is now invalid
01146          * -> another thread may have called SCardReleaseContext
01147          * -> so the mMutex has been unlocked */
01148         return SCARD_E_INVALID_HANDLE;
01149 
01150     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01151     {
01152         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01153 
01154         /* by default r == NULL */
01155         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01156             break;
01157     }
01158 
01159     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01160     {
01161         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01162         return SCARD_E_READER_UNAVAILABLE;
01163     }
01164 
01165     scBeginStruct.hCard = hCard;
01166     scBeginStruct.rv = SCARD_S_SUCCESS;
01167 
01168     /*
01169      * Query the server every so often until the sharing violation ends
01170      * and then hold the lock for yourself.
01171      */
01172 
01173     do
01174     {
01175         rv = WrapSHMWrite(SCARD_BEGIN_TRANSACTION, psContextMap[dwContextIndex].dwClientID,
01176             sizeof(scBeginStruct),
01177             PCSCLITE_CLIENT_ATTEMPTS, (void *) &scBeginStruct);
01178 
01179         if (rv == -1)
01180         {
01181 
01182             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01183             return SCARD_E_NO_SERVICE;
01184         }
01185 
01186         /*
01187          * Read a message from the server
01188          */
01189         rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01190             PCSCLITE_CLIENT_ATTEMPTS);
01191 
01192         memcpy(&scBeginStruct, &msgStruct.data, sizeof(scBeginStruct));
01193 
01194         if (rv == -1)
01195         {
01196 
01197             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01198             return SCARD_F_COMM_ERROR;
01199         }
01200 
01201     }
01202     while (scBeginStruct.rv == SCARD_E_SHARING_VIOLATION);
01203 
01204     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01205 
01206     PROFILE_END(scBeginStruct.rv);
01207 
01208     return scBeginStruct.rv;
01209 }
01210 
01251 LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
01252 {
01253     LONG rv;
01254     end_struct scEndStruct;
01255     sharedSegmentMsg msgStruct;
01256     int randnum, i;
01257     DWORD dwContextIndex, dwChannelIndex;
01258 
01259     PROFILE_START
01260 
01261     /*
01262      * Zero out everything
01263      */
01264     randnum = 0;
01265 
01266     rv = SCardCheckDaemonAvailability();
01267     if (rv != SCARD_S_SUCCESS)
01268         return rv;
01269 
01270     /*
01271      * Make sure this handle has been opened
01272      */
01273     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01274     if (rv == -1)
01275         return SCARD_E_INVALID_HANDLE;
01276 
01277     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01278 
01279     /* check the handle is still valid */
01280     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01281     if (rv == -1)
01282         /* the handle is now invalid
01283          * -> another thread may have called SCardReleaseContext
01284          * -> so the mMutex has been unlocked */
01285         return SCARD_E_INVALID_HANDLE;
01286 
01287     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01288     {
01289         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01290 
01291         /* by default r == NULL */
01292         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01293             break;
01294     }
01295 
01296     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01297     {
01298         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01299         return SCARD_E_READER_UNAVAILABLE;
01300     }
01301 
01302     scEndStruct.hCard = hCard;
01303     scEndStruct.dwDisposition = dwDisposition;
01304     scEndStruct.rv = SCARD_S_SUCCESS;
01305 
01306     rv = WrapSHMWrite(SCARD_END_TRANSACTION,
01307         psContextMap[dwContextIndex].dwClientID,
01308         sizeof(scEndStruct),
01309         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scEndStruct);
01310 
01311     if (rv == -1)
01312     {
01313         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01314         return SCARD_E_NO_SERVICE;
01315     }
01316 
01317     /*
01318      * Read a message from the server
01319      */
01320     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01321         PCSCLITE_CLIENT_ATTEMPTS);
01322 
01323     memcpy(&scEndStruct, &msgStruct.data, sizeof(scEndStruct));
01324 
01325     if (rv == -1)
01326     {
01327         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01328         return SCARD_F_COMM_ERROR;
01329     }
01330 
01331     /*
01332      * This helps prevent starvation
01333      */
01334     randnum = SYS_RandomInt(1000, 10000);
01335     SYS_USleep(randnum);
01336 
01337     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01338 
01339     PROFILE_END(scEndStruct.rv)
01340 
01341     return scEndStruct.rv;
01342 }
01343 
01350 LONG SCardCancelTransaction(SCARDHANDLE hCard)
01351 {
01352     LONG rv;
01353     cancel_struct scCancelStruct;
01354     sharedSegmentMsg msgStruct;
01355     int i;
01356     DWORD dwContextIndex, dwChannelIndex;
01357 
01358     PROFILE_START
01359 
01360     rv = SCardCheckDaemonAvailability();
01361     if (rv != SCARD_S_SUCCESS)
01362         return rv;
01363 
01364     /*
01365      * Make sure this handle has been opened
01366      */
01367     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01368     if (rv == -1)
01369         return SCARD_E_INVALID_HANDLE;
01370 
01371     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01372 
01373     /* check the handle is still valid */
01374     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01375     if (rv == -1)
01376         /* the handle is now invalid
01377          * -> another thread may have called SCardReleaseContext
01378          * -> so the mMutex has been unlocked */
01379         return SCARD_E_INVALID_HANDLE;
01380 
01381     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01382     {
01383         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01384 
01385         /* by default r == NULL */
01386         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01387             break;
01388     }
01389 
01390     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01391     {
01392         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01393         return SCARD_E_READER_UNAVAILABLE;
01394     }
01395 
01396     scCancelStruct.hCard = hCard;
01397 
01398     rv = WrapSHMWrite(SCARD_CANCEL_TRANSACTION,
01399         psContextMap[dwContextIndex].dwClientID,
01400         sizeof(scCancelStruct),
01401         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scCancelStruct);
01402 
01403     if (rv == -1)
01404     {
01405         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01406         return SCARD_E_NO_SERVICE;
01407     }
01408 
01409     /*
01410      * Read a message from the server
01411      */
01412     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01413         PCSCLITE_CLIENT_ATTEMPTS);
01414 
01415     memcpy(&scCancelStruct, &msgStruct.data, sizeof(scCancelStruct));
01416 
01417     if (rv == -1)
01418     {
01419         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01420         return SCARD_F_COMM_ERROR;
01421     }
01422 
01423     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01424 
01425     PROFILE_END(scCancelStruct.rv)
01426 
01427     return scCancelStruct.rv;
01428 }
01429 
01491 LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderNames,
01492     LPDWORD pcchReaderLen, LPDWORD pdwState,
01493     LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
01494 {
01495     DWORD dwReaderLen, dwAtrLen;
01496     LONG rv;
01497     int i;
01498     status_struct scStatusStruct;
01499     sharedSegmentMsg msgStruct;
01500     DWORD dwContextIndex, dwChannelIndex;
01501     char *r;
01502 
01503     PROFILE_START
01504 
01505     /*
01506      * Check for NULL parameters
01507      */
01508 
01509     if (pcchReaderLen == NULL || pcbAtrLen == NULL)
01510         return SCARD_E_INVALID_PARAMETER;
01511 
01512     /* length passed from caller */
01513     dwReaderLen = *pcchReaderLen;
01514     dwAtrLen = *pcbAtrLen;
01515 
01516     /* default output values */
01517     if (pdwState)
01518         *pdwState = 0;
01519 
01520     if (pdwProtocol)
01521         *pdwProtocol = 0;
01522 
01523     *pcchReaderLen = 0;
01524     *pcbAtrLen = 0;
01525 
01526     rv = SCardCheckDaemonAvailability();
01527     if (rv != SCARD_S_SUCCESS)
01528         return rv;
01529 
01530     /*
01531      * Make sure this handle has been opened
01532      */
01533     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01534     if (rv == -1)
01535         return SCARD_E_INVALID_HANDLE;
01536 
01537     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01538 
01539     /* check the handle is still valid */
01540     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01541     if (rv == -1)
01542         /* the handle is now invalid
01543          * -> another thread may have called SCardReleaseContext
01544          * -> so the mMutex has been unlocked */
01545         return SCARD_E_INVALID_HANDLE;
01546 
01547     r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01548     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01549     {
01550         /* by default r == NULL */
01551         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01552             break;
01553     }
01554 
01555     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01556     {
01557         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01558         return SCARD_E_READER_UNAVAILABLE;
01559     }
01560 
01561     /* initialise the structure */
01562     memset(&scStatusStruct, 0, sizeof(scStatusStruct));
01563     scStatusStruct.hCard = hCard;
01564 
01565     /* those sizes need to be initialised */
01566     scStatusStruct.pcchReaderLen = sizeof(scStatusStruct.mszReaderNames);
01567     scStatusStruct.pcbAtrLen = sizeof(scStatusStruct.pbAtr);
01568 
01569     rv = WrapSHMWrite(SCARD_STATUS, psContextMap[dwContextIndex].dwClientID,
01570         sizeof(scStatusStruct),
01571         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scStatusStruct);
01572 
01573     if (rv == -1)
01574     {
01575         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01576         return SCARD_E_NO_SERVICE;
01577     }
01578 
01579     /*
01580      * Read a message from the server
01581      */
01582     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
01583         PCSCLITE_CLIENT_ATTEMPTS);
01584 
01585     memcpy(&scStatusStruct, &msgStruct.data, sizeof(scStatusStruct));
01586 
01587     if (rv == -1)
01588     {
01589         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01590         return SCARD_F_COMM_ERROR;
01591     }
01592 
01593     rv = scStatusStruct.rv;
01594     if (rv != SCARD_S_SUCCESS && rv != SCARD_E_INSUFFICIENT_BUFFER)
01595     {
01596         /*
01597          * An event must have occurred
01598          */
01599         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01600         return rv;
01601     }
01602 
01603     /*
01604      * Now continue with the client side SCardStatus
01605      */
01606 
01607     *pcchReaderLen = strlen(psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName) + 1;
01608     *pcbAtrLen = (readerStates[i])->cardAtrLength;
01609 
01610     if (pdwState)
01611         *pdwState = (readerStates[i])->readerState;
01612 
01613     if (pdwProtocol)
01614         *pdwProtocol = (readerStates[i])->cardProtocol;
01615 
01616     /* return SCARD_E_INSUFFICIENT_BUFFER only if buffer pointer is non NULL */
01617     if (mszReaderNames)
01618     {
01619         if (*pcchReaderLen > dwReaderLen)
01620             rv = SCARD_E_INSUFFICIENT_BUFFER;
01621 
01622         strncpy(mszReaderNames,
01623             psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName,
01624             dwReaderLen);
01625     }
01626 
01627     if (pbAtr)
01628     {
01629         if (*pcbAtrLen > dwAtrLen)
01630             rv = SCARD_E_INSUFFICIENT_BUFFER;
01631 
01632         memcpy(pbAtr, (readerStates[i])->cardAtr,
01633             min(*pcbAtrLen, dwAtrLen));
01634     }
01635 
01636     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01637 
01638     PROFILE_END(rv)
01639 
01640     return rv;
01641 }
01642 
01730 LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout,
01731     LPSCARD_READERSTATE_A rgReaderStates, DWORD cReaders)
01732 {
01733     PSCARD_READERSTATE_A currReader;
01734     PREADER_STATE rContext;
01735     DWORD dwTime = 0;
01736     DWORD dwState;
01737     DWORD dwBreakFlag = 0;
01738     int j;
01739     LONG dwContextIndex;
01740     int currentReaderCount = 0;
01741     LONG rv;
01742 
01743     PROFILE_START
01744 
01745     if (rgReaderStates == NULL && cReaders > 0)
01746         return SCARD_E_INVALID_PARAMETER;
01747 
01748     rv = SCardCheckDaemonAvailability();
01749     if (rv != SCARD_S_SUCCESS)
01750         return rv;
01751 
01752     /*
01753      * Make sure this context has been opened
01754      */
01755 
01756     dwContextIndex = SCardGetContextIndice(hContext);
01757     if (dwContextIndex == -1)
01758         return SCARD_E_INVALID_HANDLE;
01759 
01760     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
01761 
01762     /* check the context is still opened */
01763     dwContextIndex = SCardGetContextIndice(hContext);
01764     if (dwContextIndex == -1)
01765         /* the context is now invalid
01766          * -> another thread may have called SCardReleaseContext
01767          * -> so the mMutex has been unlocked */
01768         return SCARD_E_INVALID_HANDLE;
01769 
01770     /*
01771      * Application is waiting for a reader - return the first available
01772      * reader
01773      */
01774 
01775     if (cReaders == 0)
01776     {
01777         while (1)
01778         {
01779             int i;
01780 
01781             rv = SCardCheckDaemonAvailability();
01782             if (rv != SCARD_S_SUCCESS)
01783             {
01784                 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01785                 return rv;
01786             }
01787 
01788             for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01789             {
01790                 if ((readerStates[i])->readerID != 0)
01791                 {
01792                     /*
01793                      * Reader was found
01794                      */
01795                     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01796 
01797                     PROFILE_END(SCARD_S_SUCCESS)
01798 
01799                     return SCARD_S_SUCCESS;
01800                 }
01801             }
01802 
01803             if (dwTimeout == 0)
01804             {
01805                 /*
01806                  * return immediately - no reader available
01807                  */
01808                 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01809                 return SCARD_E_READER_UNAVAILABLE;
01810             }
01811 
01812             SYS_USleep(PCSCLITE_STATUS_WAIT);
01813 
01814             if (dwTimeout != INFINITE)
01815             {
01816                 dwTime += PCSCLITE_STATUS_WAIT;
01817 
01818                 if (dwTime >= (dwTimeout * 1000))
01819                 {
01820                     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01821 
01822                     PROFILE_END(SCARD_E_TIMEOUT)
01823 
01824                     return SCARD_E_TIMEOUT;
01825                 }
01826             }
01827         }
01828     }
01829     else
01830         if (cReaders >= PCSCLITE_MAX_READERS_CONTEXTS)
01831         {
01832             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01833             return SCARD_E_INVALID_VALUE;
01834         }
01835 
01836     /*
01837      * Check the integrity of the reader states structures
01838      */
01839 
01840     for (j = 0; j < cReaders; j++)
01841     {
01842         currReader = &rgReaderStates[j];
01843 
01844         if (currReader->szReader == NULL)
01845         {
01846             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01847             return SCARD_E_INVALID_VALUE;
01848         }
01849     }
01850 
01851     /*
01852      * End of search for readers
01853      */
01854 
01855     /*
01856      * Clear the event state for all readers
01857      */
01858     for (j = 0; j < cReaders; j++)
01859     {
01860         currReader = &rgReaderStates[j];
01861         currReader->dwEventState = 0;
01862     }
01863 
01864     /*
01865      * Now is where we start our event checking loop
01866      */
01867 
01868     Log1(PCSC_LOG_DEBUG, "Event Loop Start");
01869 
01870     psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_BLOCKING;
01871 
01872     /* Get the initial reader count on the system */
01873     for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++)
01874         if ((readerStates[j])->readerID != 0)
01875             currentReaderCount++;
01876 
01877     j = 0;
01878 
01879     do
01880     {
01881         int newReaderCount = 0;
01882         char ReaderCountChanged = FALSE;
01883 
01884         rv = SCardCheckDaemonAvailability();
01885         if (rv != SCARD_S_SUCCESS)
01886         {
01887             if (psContextMap[dwContextIndex].mMutex)
01888                 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
01889 
01890             PROFILE_END(rv)
01891 
01892             return rv;
01893         }
01894 
01895         if (j == 0)
01896         {
01897             int i;
01898 
01899             for (i=0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01900                 if ((readerStates[i])->readerID != 0)
01901                     newReaderCount++;
01902 
01903             if (newReaderCount != currentReaderCount)
01904             {
01905                 Log1(PCSC_LOG_INFO, "Reader list changed");
01906                 ReaderCountChanged = TRUE;
01907                 currentReaderCount = newReaderCount;
01908             }
01909         }
01910         currReader = &rgReaderStates[j];
01911 
01912     /************ Look for IGNORED readers ****************************/
01913 
01914         if (currReader->dwCurrentState & SCARD_STATE_IGNORE)
01915             currReader->dwEventState = SCARD_STATE_IGNORE;
01916         else
01917         {
01918             LPSTR lpcReaderName;
01919             int i;
01920 
01921       /************ Looks for correct readernames *********************/
01922 
01923             lpcReaderName = (char *) currReader->szReader;
01924 
01925             for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01926             {
01927                 if (strcmp(lpcReaderName, (readerStates[i])->readerName) == 0)
01928                     break;
01929             }
01930 
01931             /*
01932              * The requested reader name is not recognized
01933              */
01934             if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01935             {
01936                 if (currReader->dwCurrentState & SCARD_STATE_UNKNOWN)
01937                     currReader->dwEventState = SCARD_STATE_UNKNOWN;
01938                 else
01939                 {
01940                     currReader->dwEventState =
01941                         SCARD_STATE_UNKNOWN | SCARD_STATE_CHANGED;
01942                     /*
01943                      * Spec says use SCARD_STATE_IGNORE but a removed USB
01944                      * reader with eventState fed into currentState will
01945                      * be ignored forever
01946                      */
01947                     dwBreakFlag = 1;
01948                 }
01949             }
01950             else
01951             {
01952 
01953                 /*
01954                  * The reader has come back after being away
01955                  */
01956                 if (currReader->dwCurrentState & SCARD_STATE_UNKNOWN)
01957                 {
01958                     currReader->dwEventState |= SCARD_STATE_CHANGED;
01959                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
01960                     dwBreakFlag = 1;
01961                 }
01962 
01963     /*****************************************************************/
01964 
01965                 /*
01966                  * Set the reader status structure
01967                  */
01968                 rContext = readerStates[i];
01969 
01970                 /*
01971                  * Now we check all the Reader States
01972                  */
01973                 dwState = rContext->readerState;
01974                 {
01975                     int currentCounter, stateCounter;
01976 
01977                     stateCounter = (dwState >> 16) & 0xFFFF;
01978                     currentCounter = (currReader->dwCurrentState >> 16) & 0xFFFF;
01979 
01980                     /* has the event counter changed since the last call? */
01981                     if (stateCounter != currentCounter)
01982                         currReader->dwEventState |= SCARD_STATE_CHANGED;
01983 
01984                     /* add an event counter in the upper word of dwEventState */
01985                     currReader->dwEventState =
01986                         ((currReader->dwEventState & 0xffff )
01987                         | (stateCounter << 16));
01988                 }
01989 
01990     /*********** Check if the reader is in the correct state ********/
01991                 if (dwState & SCARD_UNKNOWN)
01992                 {
01993                     /*
01994                      * App thinks reader is in bad state and it is
01995                      */
01996                     if (currReader-> dwCurrentState & SCARD_STATE_UNAVAILABLE)
01997                         currReader->dwEventState = SCARD_STATE_UNAVAILABLE;
01998                     else
01999                     {
02000                         /*
02001                          * App thinks reader is in good state and it is
02002                          * not
02003                          */
02004                         currReader->dwEventState = SCARD_STATE_CHANGED |
02005                             SCARD_STATE_UNAVAILABLE;
02006                         dwBreakFlag = 1;
02007                     }
02008                 }
02009                 else
02010                 {
02011                     /*
02012                      * App thinks reader in bad state but it is not
02013                      */
02014                     if (currReader-> dwCurrentState & SCARD_STATE_UNAVAILABLE)
02015                     {
02016                         currReader->dwEventState &=
02017                             ~SCARD_STATE_UNAVAILABLE;
02018                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02019                         dwBreakFlag = 1;
02020                     }
02021                 }
02022 
02023     /********** Check for card presence in the reader **************/
02024 
02025                 if (dwState & SCARD_PRESENT)
02026                 {
02027                     /* card present but not yet powered up */
02028                     if (0 == rContext->cardAtrLength)
02029                         /* Allow the status thread to convey information */
02030                         SYS_USleep(PCSCLITE_STATUS_POLL_RATE + 10);
02031 
02032                     currReader->cbAtr = rContext->cardAtrLength;
02033                     memcpy(currReader->rgbAtr, rContext->cardAtr,
02034                         currReader->cbAtr);
02035                 }
02036                 else
02037                     currReader->cbAtr = 0;
02038 
02039                 /*
02040                  * Card is now absent
02041                  */
02042                 if (dwState & SCARD_ABSENT)
02043                 {
02044                     currReader->dwEventState |= SCARD_STATE_EMPTY;
02045                     currReader->dwEventState &= ~SCARD_STATE_PRESENT;
02046                     currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
02047                     currReader->dwEventState &= ~SCARD_STATE_IGNORE;
02048                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
02049                     currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
02050                     currReader->dwEventState &= ~SCARD_STATE_ATRMATCH;
02051                     currReader->dwEventState &= ~SCARD_STATE_MUTE;
02052                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
02053 
02054                     /*
02055                      * After present the rest are assumed
02056                      */
02057                     if (currReader->dwCurrentState & SCARD_STATE_PRESENT)
02058                     {
02059                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02060                         dwBreakFlag = 1;
02061                     }
02062 
02063                     /*
02064                      * Card is now present
02065                      */
02066                 } else if (dwState & SCARD_PRESENT)
02067                 {
02068                     currReader->dwEventState |= SCARD_STATE_PRESENT;
02069                     currReader->dwEventState &= ~SCARD_STATE_EMPTY;
02070                     currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
02071                     currReader->dwEventState &= ~SCARD_STATE_IGNORE;
02072                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
02073                     currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
02074                     currReader->dwEventState &= ~SCARD_STATE_MUTE;
02075 
02076                     if (currReader->dwCurrentState & SCARD_STATE_EMPTY)
02077                     {
02078                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02079                         dwBreakFlag = 1;
02080                     }
02081 
02082                     if (dwState & SCARD_SWALLOWED)
02083                     {
02084                         if (currReader->dwCurrentState & SCARD_STATE_MUTE)
02085                             currReader->dwEventState |= SCARD_STATE_MUTE;
02086                         else
02087                         {
02088                             currReader->dwEventState |= SCARD_STATE_MUTE;
02089                             if (currReader->dwCurrentState
02090                                 != SCARD_STATE_UNAWARE)
02091                                 currReader->dwEventState |= SCARD_STATE_CHANGED;
02092                             dwBreakFlag = 1;
02093                         }
02094                     }
02095                     else
02096                     {
02097                         /*
02098                          * App thinks card is mute but it is not
02099                          */
02100                         if (currReader->dwCurrentState & SCARD_STATE_MUTE)
02101                         {
02102                             currReader->dwEventState |=
02103                                 SCARD_STATE_CHANGED;
02104                             dwBreakFlag = 1;
02105                         }
02106                     }
02107                 }
02108 
02109                 /*
02110                  * Now figure out sharing modes
02111                  */
02112                 if (rContext->readerSharing == -1)
02113                 {
02114                     currReader->dwEventState |= SCARD_STATE_EXCLUSIVE;
02115                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
02116                     if (currReader->dwCurrentState & SCARD_STATE_INUSE)
02117                     {
02118                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02119                         dwBreakFlag = 1;
02120                     }
02121                 }
02122                 else if (rContext->readerSharing >= 1)
02123                 {
02124                     /*
02125                      * A card must be inserted for it to be INUSE
02126                      */
02127                     if (dwState & SCARD_PRESENT)
02128                     {
02129                         currReader->dwEventState |= SCARD_STATE_INUSE;
02130                         currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
02131                         if (currReader-> dwCurrentState & SCARD_STATE_EXCLUSIVE)
02132                         {
02133                             currReader->dwEventState |= SCARD_STATE_CHANGED;
02134                             dwBreakFlag = 1;
02135                         }
02136                     }
02137                 }
02138                 else if (rContext->readerSharing == 0)
02139                 {
02140                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
02141                     currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
02142 
02143                     if (currReader->dwCurrentState & SCARD_STATE_INUSE)
02144                     {
02145                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02146                         dwBreakFlag = 1;
02147                     }
02148                     else if (currReader-> dwCurrentState
02149                         & SCARD_STATE_EXCLUSIVE)
02150                     {
02151                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02152                         dwBreakFlag = 1;
02153                     }
02154                 }
02155 
02156                 if (currReader->dwCurrentState == SCARD_STATE_UNAWARE)
02157                 {
02158                     /*
02159                      * Break out of the while .. loop and return status
02160                      * once all the status's for all readers is met
02161                      */
02162                     currReader->dwEventState |= SCARD_STATE_CHANGED;
02163                     dwBreakFlag = 1;
02164                 }
02165 
02166             }   /* End of SCARD_STATE_UNKNOWN */
02167 
02168         }   /* End of SCARD_STATE_IGNORE */
02169 
02170         /*
02171          * Counter and resetter
02172          */
02173         j = j + 1;
02174         if (j == cReaders)
02175         {
02176             if (!dwBreakFlag)
02177             {
02178                 /* break if the reader count changed,
02179                  * so that the calling application can update
02180                  * the reader list
02181                  */
02182                 if (ReaderCountChanged)
02183                     break;
02184             }
02185             j = 0;
02186         }
02187 
02188         /*
02189          * Declare all the break conditions
02190          */
02191 
02192         if (psContextMap[dwContextIndex].contextBlockStatus
02193                 == BLOCK_STATUS_RESUME)
02194             break;
02195 
02196         /*
02197          * Break if UNAWARE is set and all readers have been checked
02198          */
02199         if ((dwBreakFlag == 1) && (j == 0))
02200             break;
02201 
02202         /*
02203          * Timeout has occurred and all readers checked
02204          */
02205         if ((dwTimeout == 0) && (j == 0))
02206             break;
02207 
02208         if (dwTimeout != INFINITE && dwTimeout != 0)
02209         {
02210             /*
02211              * If time is greater than timeout and all readers have been
02212              * checked
02213              */
02214             if ((dwTime >= (dwTimeout * 1000)) && (j == 0))
02215             {
02216                 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02217                 PROFILE_END(SCARD_E_TIMEOUT)
02218                 return SCARD_E_TIMEOUT;
02219             }
02220         }
02221 
02222         /*
02223          * Only sleep once for each cycle of reader checks.
02224          */
02225         if (j == 0)
02226         {
02227             SYS_USleep(PCSCLITE_STATUS_WAIT);
02228             dwTime += PCSCLITE_STATUS_WAIT;
02229         }
02230     }
02231     while (1);
02232 
02233     Log1(PCSC_LOG_DEBUG, "Event Loop End");
02234 
02235     if (psContextMap[dwContextIndex].contextBlockStatus ==
02236             BLOCK_STATUS_RESUME)
02237     {
02238         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02239         PROFILE_END(SCARD_E_CANCELLED)
02240         return SCARD_E_CANCELLED;
02241     }
02242 
02243     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02244 
02245     PROFILE_END(SCARD_S_SUCCESS)
02246 
02247     return SCARD_S_SUCCESS;
02248 }
02249 
02302 LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,
02303     DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
02304     LPDWORD lpBytesReturned)
02305 {
02306     LONG rv;
02307     control_struct scControlStruct;
02308     sharedSegmentMsg msgStruct;
02309     int i;
02310     DWORD dwContextIndex, dwChannelIndex;
02311 
02312     PROFILE_START
02313 
02314     /* 0 bytes received by default */
02315     if (NULL != lpBytesReturned)
02316         *lpBytesReturned = 0;
02317 
02318     rv = SCardCheckDaemonAvailability();
02319     if (rv != SCARD_S_SUCCESS)
02320         return rv;
02321 
02322     /*
02323      * Make sure this handle has been opened
02324      */
02325     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02326     if (rv == -1)
02327         return SCARD_E_INVALID_HANDLE;
02328 
02329     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
02330 
02331     /* check the handle is still valid */
02332     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02333     if (rv == -1)
02334         /* the handle is now invalid
02335          * -> another thread may have called SCardReleaseContext
02336          * -> so the mMutex has been unlocked */
02337         return SCARD_E_INVALID_HANDLE;
02338 
02339     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02340     {
02341         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02342 
02343         /* by default r == NULL */
02344         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02345             break;
02346     }
02347 
02348     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02349     {
02350         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02351         return SCARD_E_READER_UNAVAILABLE;
02352     }
02353 
02354     if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
02355         || (cbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
02356     {
02357         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02358         return SCARD_E_INSUFFICIENT_BUFFER;
02359     }
02360 
02361     if ((cbSendLength > MAX_BUFFER_SIZE) || (cbRecvLength > MAX_BUFFER_SIZE))
02362     {
02363         /* extended control */
02364         unsigned char buffer[sizeof(sharedSegmentMsg) + MAX_BUFFER_SIZE_EXTENDED];
02365         control_struct_extended *scControlStructExtended = (control_struct_extended *)buffer;
02366         sharedSegmentMsg *pmsgStruct = (psharedSegmentMsg)buffer;
02367 
02368         scControlStructExtended->hCard = hCard;
02369         scControlStructExtended->dwControlCode = dwControlCode;
02370         scControlStructExtended->cbSendLength = cbSendLength;
02371         scControlStructExtended->cbRecvLength = cbRecvLength;
02372         scControlStructExtended->pdwBytesReturned = 0;
02373         scControlStructExtended->rv = SCARD_S_SUCCESS;
02374         /* The size of data to send is the size of
02375          * struct control_struct_extended WITHOUT the data[] field
02376          * plus the effective data[] size
02377          */
02378         scControlStructExtended->size = sizeof(*scControlStructExtended)
02379             - (sizeof(control_struct_extended) - offsetof(control_struct_extended, data))
02380             + cbSendLength;
02381         memcpy(scControlStructExtended->data, pbSendBuffer, cbSendLength);
02382 
02383         rv = WrapSHMWrite(SCARD_CONTROL_EXTENDED,
02384             psContextMap[dwContextIndex].dwClientID,
02385             scControlStructExtended->size,
02386             PCSCLITE_CLIENT_ATTEMPTS, buffer);
02387 
02388         if (rv == -1)
02389         {
02390             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02391             return SCARD_E_NO_SERVICE;
02392         }
02393 
02394         /*
02395          * Read a message from the server
02396          */
02397         /* read the first block */
02398         rv = SHMMessageReceive(buffer, sizeof(sharedSegmentMsg),
02399             psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
02400         if (rv == -1)
02401         {
02402             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02403             return SCARD_F_COMM_ERROR;
02404         }
02405 
02406         /* we receive a sharedSegmentMsg and not a control_struct_extended */
02407         scControlStructExtended = (control_struct_extended *)&(pmsgStruct -> data);
02408 
02409         /* a second block is present */
02410         if (scControlStructExtended->size > PCSCLITE_MAX_MESSAGE_SIZE)
02411         {
02412             rv = SHMMessageReceive(buffer + sizeof(sharedSegmentMsg),
02413                 scControlStructExtended->size-PCSCLITE_MAX_MESSAGE_SIZE,
02414                 psContextMap[dwContextIndex].dwClientID,
02415                 PCSCLITE_CLIENT_ATTEMPTS);
02416             if (rv == -1)
02417             {
02418                 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02419                 return SCARD_F_COMM_ERROR;
02420             }
02421         }
02422 
02423         if (scControlStructExtended -> rv == SCARD_S_SUCCESS)
02424         {
02425             /*
02426              * Copy and zero it so any secret information is not leaked
02427              */
02428             memcpy(pbRecvBuffer, scControlStructExtended -> data,
02429                 scControlStructExtended -> pdwBytesReturned);
02430             memset(scControlStructExtended -> data, 0x00,
02431                 scControlStructExtended -> pdwBytesReturned);
02432         }
02433 
02434         if (NULL != lpBytesReturned)
02435             *lpBytesReturned = scControlStructExtended -> pdwBytesReturned;
02436 
02437         rv = scControlStructExtended -> rv;
02438     }
02439     else
02440     {
02441         scControlStruct.hCard = hCard;
02442         scControlStruct.dwControlCode = dwControlCode;
02443         scControlStruct.cbSendLength = cbSendLength;
02444         scControlStruct.cbRecvLength = cbRecvLength;
02445         memcpy(scControlStruct.pbSendBuffer, pbSendBuffer, cbSendLength);
02446 
02447         rv = WrapSHMWrite(SCARD_CONTROL,
02448             psContextMap[dwContextIndex].dwClientID,
02449             sizeof(scControlStruct), PCSCLITE_CLIENT_ATTEMPTS, &scControlStruct);
02450 
02451         if (rv == -1)
02452         {
02453             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02454             return SCARD_E_NO_SERVICE;
02455         }
02456 
02457         /*
02458          * Read a message from the server
02459          */
02460         rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
02461             PCSCLITE_CLIENT_ATTEMPTS);
02462 
02463         if (rv == -1)
02464         {
02465             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02466             return SCARD_F_COMM_ERROR;
02467         }
02468 
02469         memcpy(&scControlStruct, &msgStruct.data, sizeof(scControlStruct));
02470 
02471         if (NULL != lpBytesReturned)
02472             *lpBytesReturned = scControlStruct.dwBytesReturned;
02473 
02474         if (scControlStruct.rv == SCARD_S_SUCCESS)
02475         {
02476             /*
02477              * Copy and zero it so any secret information is not leaked
02478              */
02479             memcpy(pbRecvBuffer, scControlStruct.pbRecvBuffer,
02480                 scControlStruct.cbRecvLength);
02481             memset(scControlStruct.pbRecvBuffer, 0x00,
02482                 sizeof(scControlStruct.pbRecvBuffer));
02483         }
02484 
02485         rv = scControlStruct.rv;
02486     }
02487 
02488     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02489 
02490     PROFILE_END(rv)
02491 
02492     return rv;
02493 }
02494 
02576 LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr,
02577     LPDWORD pcbAttrLen)
02578 {
02579     LONG ret;
02580     unsigned char *buf = NULL;
02581 
02582     PROFILE_START
02583 
02584     if (NULL == pcbAttrLen)
02585         return SCARD_E_INVALID_PARAMETER;
02586 
02587     if (SCARD_AUTOALLOCATE == *pcbAttrLen)
02588     {
02589         *pcbAttrLen = MAX_BUFFER_SIZE;
02590         buf = malloc(*pcbAttrLen);
02591         if (NULL == buf)
02592             return SCARD_E_NO_MEMORY;
02593 
02594         *(unsigned char **)pbAttr = buf;
02595     }
02596     else
02597     {
02598         buf = pbAttr;
02599 
02600         /* if only get the length */
02601         if (NULL == pbAttr)
02602             /* use a reasonable size */
02603             *pcbAttrLen = MAX_BUFFER_SIZE;
02604     }
02605 
02606     ret = SCardGetSetAttrib(hCard, SCARD_GET_ATTRIB, dwAttrId, buf,
02607         pcbAttrLen);
02608 
02609     PROFILE_END(ret)
02610 
02611     return ret;
02612 }
02613 
02649 LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr,
02650     DWORD cbAttrLen)
02651 {
02652     LONG ret;
02653 
02654     PROFILE_START
02655 
02656     if (NULL == pbAttr || 0 == cbAttrLen)
02657         return SCARD_E_INVALID_PARAMETER;
02658 
02659     ret = SCardGetSetAttrib(hCard, SCARD_SET_ATTRIB, dwAttrId, (LPBYTE)pbAttr,
02660         &cbAttrLen);
02661 
02662     PROFILE_END(ret)
02663 
02664     return ret;
02665 }
02666 
02667 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
02668     LPBYTE pbAttr, LPDWORD pcbAttrLen)
02669 {
02670     LONG rv;
02671     getset_struct scGetSetStruct;
02672     sharedSegmentMsg msgStruct;
02673     int i;
02674     DWORD dwContextIndex, dwChannelIndex;
02675 
02676     rv = SCardCheckDaemonAvailability();
02677     if (rv != SCARD_S_SUCCESS)
02678         return rv;
02679 
02680     /*
02681      * Make sure this handle has been opened
02682      */
02683     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02684     if (rv == -1)
02685         return SCARD_E_INVALID_HANDLE;
02686 
02687     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
02688 
02689     /* check the handle is still valid */
02690     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02691     if (rv == -1)
02692         /* the handle is now invalid
02693          * -> another thread may have called SCardReleaseContext
02694          * -> so the mMutex has been unlocked */
02695         return SCARD_E_INVALID_HANDLE;
02696 
02697     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02698     {
02699         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02700 
02701         /* by default r == NULL */
02702         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02703             break;
02704     }
02705 
02706     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02707     {
02708         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02709         return SCARD_E_READER_UNAVAILABLE;
02710     }
02711 
02712     if (*pcbAttrLen > MAX_BUFFER_SIZE)
02713     {
02714         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02715         return SCARD_E_INSUFFICIENT_BUFFER;
02716     }
02717 
02718     scGetSetStruct.hCard = hCard;
02719     scGetSetStruct.dwAttrId = dwAttrId;
02720     scGetSetStruct.cbAttrLen = *pcbAttrLen;
02721     scGetSetStruct.rv = SCARD_E_NO_SERVICE;
02722     memset(scGetSetStruct.pbAttr, 0, sizeof(scGetSetStruct.pbAttr));
02723     if (SCARD_SET_ATTRIB == command)
02724         memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
02725 
02726     rv = WrapSHMWrite(command,
02727         psContextMap[dwContextIndex].dwClientID, sizeof(scGetSetStruct),
02728         PCSCLITE_CLIENT_ATTEMPTS, &scGetSetStruct);
02729 
02730     if (rv == -1)
02731     {
02732         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02733         return SCARD_E_NO_SERVICE;
02734     }
02735 
02736     /*
02737      * Read a message from the server
02738      */
02739     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
02740         PCSCLITE_CLIENT_ATTEMPTS);
02741 
02742     if (rv == -1)
02743     {
02744         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02745         return SCARD_F_COMM_ERROR;
02746     }
02747 
02748     memcpy(&scGetSetStruct, &msgStruct.data, sizeof(scGetSetStruct));
02749 
02750     if ((SCARD_S_SUCCESS == scGetSetStruct.rv) && (SCARD_GET_ATTRIB == command))
02751     {
02752         /*
02753          * Copy and zero it so any secret information is not leaked
02754          */
02755         if (*pcbAttrLen < scGetSetStruct.cbAttrLen)
02756         {
02757             scGetSetStruct.cbAttrLen = *pcbAttrLen;
02758             scGetSetStruct.rv = SCARD_E_INSUFFICIENT_BUFFER;
02759         }
02760         else
02761             *pcbAttrLen = scGetSetStruct.cbAttrLen;
02762 
02763         if (pbAttr)
02764             memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen);
02765 
02766         memset(scGetSetStruct.pbAttr, 0x00, sizeof(scGetSetStruct.pbAttr));
02767     }
02768 
02769     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02770 
02771     return scGetSetStruct.rv;
02772 }
02773 
02830 LONG SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci,
02831     LPCBYTE pbSendBuffer, DWORD cbSendLength,
02832     LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer,
02833     LPDWORD pcbRecvLength)
02834 {
02835     LONG rv;
02836     int i;
02837     DWORD dwContextIndex, dwChannelIndex;
02838 
02839     PROFILE_START
02840 
02841     if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
02842             pcbRecvLength == NULL || pioSendPci == NULL)
02843         return SCARD_E_INVALID_PARAMETER;
02844 
02845     rv = SCardCheckDaemonAvailability();
02846     if (rv != SCARD_S_SUCCESS)
02847         return rv;
02848 
02849     /*
02850      * Make sure this handle has been opened
02851      */
02852     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02853     if (rv == -1)
02854     {
02855         *pcbRecvLength = 0;
02856         return SCARD_E_INVALID_HANDLE;
02857     }
02858 
02859     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
02860 
02861     /* check the handle is still valid */
02862     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02863     if (rv == -1)
02864         /* the handle is now invalid
02865          * -> another thread may have called SCardReleaseContext
02866          * -> so the mMutex has been unlocked */
02867         return SCARD_E_INVALID_HANDLE;
02868 
02869     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02870     {
02871         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02872 
02873         /* by default r == NULL */
02874         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02875             break;
02876     }
02877 
02878     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02879     {
02880         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02881         return SCARD_E_READER_UNAVAILABLE;
02882     }
02883 
02884     if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
02885         || (*pcbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
02886     {
02887         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02888         return SCARD_E_INSUFFICIENT_BUFFER;
02889     }
02890 
02891     if ((cbSendLength > MAX_BUFFER_SIZE) || (*pcbRecvLength > MAX_BUFFER_SIZE))
02892     {
02893         /* extended APDU */
02894         unsigned char buffer[sizeof(sharedSegmentMsg) + MAX_BUFFER_SIZE_EXTENDED];
02895         transmit_struct_extended *scTransmitStructExtended = (transmit_struct_extended *)buffer;
02896         sharedSegmentMsg *pmsgStruct = (psharedSegmentMsg)buffer;
02897 
02898         scTransmitStructExtended->hCard = hCard;
02899         scTransmitStructExtended->cbSendLength = cbSendLength;
02900         scTransmitStructExtended->pcbRecvLength = *pcbRecvLength;
02901         /* The size of data to send is the size of
02902          * struct control_struct_extended WITHOUT the data[] field
02903          * plus the effective data[] size
02904          */
02905         scTransmitStructExtended->size = sizeof(*scTransmitStructExtended)
02906             - (sizeof(transmit_struct_extended) - offsetof(transmit_struct_extended, data))
02907             + cbSendLength;
02908         scTransmitStructExtended->pioSendPciProtocol = pioSendPci->dwProtocol;
02909         scTransmitStructExtended->pioSendPciLength = pioSendPci->cbPciLength;
02910         memcpy(scTransmitStructExtended->data, pbSendBuffer, cbSendLength);
02911         scTransmitStructExtended->rv = SCARD_S_SUCCESS;
02912 
02913         if (pioRecvPci)
02914         {
02915             scTransmitStructExtended->pioRecvPciProtocol = pioRecvPci->dwProtocol;
02916             scTransmitStructExtended->pioRecvPciLength = pioRecvPci->cbPciLength;
02917         }
02918         else
02919         {
02920             scTransmitStructExtended->pioRecvPciProtocol = SCARD_PROTOCOL_ANY;
02921             scTransmitStructExtended->pioRecvPciLength = sizeof(SCARD_IO_REQUEST);
02922         }
02923 
02924         rv = WrapSHMWrite(SCARD_TRANSMIT_EXTENDED,
02925             psContextMap[dwContextIndex].dwClientID,
02926             scTransmitStructExtended->size,
02927             PCSCLITE_CLIENT_ATTEMPTS, buffer);
02928 
02929         if (rv == -1)
02930         {
02931             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02932             return SCARD_E_NO_SERVICE;
02933         }
02934 
02935         /*
02936          * Read a message from the server
02937          */
02938         /* read the first block */
02939         rv = SHMMessageReceive(buffer, sizeof(sharedSegmentMsg), psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
02940         if (rv == -1)
02941         {
02942             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02943             return SCARD_F_COMM_ERROR;
02944         }
02945 
02946         /* we receive a sharedSegmentMsg and not a transmit_struct_extended */
02947         scTransmitStructExtended = (transmit_struct_extended *)&(pmsgStruct -> data);
02948 
02949         /* a second block is present */
02950         if (scTransmitStructExtended->size > PCSCLITE_MAX_MESSAGE_SIZE)
02951         {
02952             rv = SHMMessageReceive(buffer + sizeof(sharedSegmentMsg),
02953                 scTransmitStructExtended->size-PCSCLITE_MAX_MESSAGE_SIZE,
02954                 psContextMap[dwContextIndex].dwClientID,
02955                 PCSCLITE_CLIENT_ATTEMPTS);
02956             if (rv == -1)
02957             {
02958                 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02959                 return SCARD_F_COMM_ERROR;
02960             }
02961         }
02962 
02963         if (scTransmitStructExtended -> rv == SCARD_S_SUCCESS)
02964         {
02965             /*
02966              * Copy and zero it so any secret information is not leaked
02967              */
02968             memcpy(pbRecvBuffer, scTransmitStructExtended -> data,
02969                 scTransmitStructExtended -> pcbRecvLength);
02970             memset(scTransmitStructExtended -> data, 0x00,
02971                 scTransmitStructExtended -> pcbRecvLength);
02972 
02973             if (pioRecvPci)
02974             {
02975                 pioRecvPci->dwProtocol = scTransmitStructExtended->pioRecvPciProtocol;
02976                 pioRecvPci->cbPciLength = scTransmitStructExtended->pioRecvPciLength;
02977             }
02978         }
02979 
02980         *pcbRecvLength = scTransmitStructExtended -> pcbRecvLength;
02981         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
02982 
02983         rv = scTransmitStructExtended -> rv;
02984     }
02985     else
02986     {
02987         /* short APDU */
02988         transmit_struct scTransmitStruct;
02989         sharedSegmentMsg msgStruct;
02990 
02991         scTransmitStruct.hCard = hCard;
02992         scTransmitStruct.cbSendLength = cbSendLength;
02993         scTransmitStruct.pcbRecvLength = *pcbRecvLength;
02994         scTransmitStruct.pioSendPciProtocol = pioSendPci->dwProtocol;
02995         scTransmitStruct.pioSendPciLength = pioSendPci->cbPciLength;
02996         memcpy(scTransmitStruct.pbSendBuffer, pbSendBuffer, cbSendLength);
02997         memset(scTransmitStruct.pbSendBuffer+cbSendLength, 0, sizeof(scTransmitStruct.pbSendBuffer)-cbSendLength);
02998         memset(scTransmitStruct.pbRecvBuffer, 0, sizeof(scTransmitStruct.pbRecvBuffer));
02999         scTransmitStruct.rv = SCARD_S_SUCCESS;
03000 
03001         scTransmitStruct.pioRecvPciProtocol = SCARD_PROTOCOL_ANY;
03002         scTransmitStruct.pioRecvPciLength = sizeof(SCARD_IO_REQUEST);
03003 
03004         rv = WrapSHMWrite(SCARD_TRANSMIT,
03005             psContextMap[dwContextIndex].dwClientID, sizeof(scTransmitStruct),
03006             PCSCLITE_CLIENT_ATTEMPTS, (void *) &scTransmitStruct);
03007 
03008         if (rv == -1)
03009         {
03010             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03011             return SCARD_E_NO_SERVICE;
03012         }
03013 
03014         /*
03015          * Read a message from the server
03016          */
03017         rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
03018             PCSCLITE_CLIENT_ATTEMPTS);
03019 
03020         memcpy(&scTransmitStruct, &msgStruct.data, sizeof(scTransmitStruct));
03021 
03022         if (rv == -1)
03023         {
03024             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03025             return SCARD_F_COMM_ERROR;
03026         }
03027 
03028         /*
03029          * Zero it and free it so any secret information cannot be leaked
03030          */
03031         memset(scTransmitStruct.pbSendBuffer, 0x00, cbSendLength);
03032 
03033         if (scTransmitStruct.rv == SCARD_S_SUCCESS)
03034         {
03035             /*
03036              * Copy and zero it so any secret information is not leaked
03037              */
03038             memcpy(pbRecvBuffer, scTransmitStruct.pbRecvBuffer,
03039                 scTransmitStruct.pcbRecvLength);
03040             memset(scTransmitStruct.pbRecvBuffer, 0x00,
03041                 scTransmitStruct.pcbRecvLength);
03042 
03043             if (pioRecvPci)
03044             {
03045                 pioRecvPci->dwProtocol = scTransmitStruct.pioRecvPciProtocol;
03046                 pioRecvPci->cbPciLength = scTransmitStruct.pioRecvPciLength;
03047             }
03048         }
03049 
03050         *pcbRecvLength = scTransmitStruct.pcbRecvLength;
03051         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03052 
03053         rv = scTransmitStruct.rv;
03054     }
03055 
03056     PROFILE_END(rv)
03057 
03058     return rv;
03059 }
03060 
03094 LONG SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups,
03095     LPSTR mszReaders, LPDWORD pcchReaders)
03096 {
03097     DWORD dwReadersLen;
03098     int i;
03099     LONG dwContextIndex;
03100     LONG rv = SCARD_S_SUCCESS;
03101     char *buf = NULL;
03102 
03103     PROFILE_START
03104 
03105     /*
03106      * Check for NULL parameters
03107      */
03108     if (pcchReaders == NULL)
03109         return SCARD_E_INVALID_PARAMETER;
03110 
03111     rv = SCardCheckDaemonAvailability();
03112     if (rv != SCARD_S_SUCCESS)
03113         return rv;
03114 
03115     /*
03116      * Make sure this context has been opened
03117      */
03118     dwContextIndex = SCardGetContextIndice(hContext);
03119     if (dwContextIndex == -1)
03120         return SCARD_E_INVALID_HANDLE;
03121 
03122     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
03123 
03124     /* check the context is still opened */
03125     dwContextIndex = SCardGetContextIndice(hContext);
03126     if (dwContextIndex == -1)
03127         /* the context is now invalid
03128          * -> another thread may have called SCardReleaseContext
03129          * -> so the mMutex has been unlocked */
03130         return SCARD_E_INVALID_HANDLE;
03131 
03132     dwReadersLen = 0;
03133     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
03134         if ((readerStates[i])->readerID != 0)
03135             dwReadersLen += strlen((readerStates[i])->readerName) + 1;
03136 
03137     /* for the last NULL byte */
03138     dwReadersLen += 1;
03139 
03140     if (1 == dwReadersLen)
03141     {
03142         rv = SCARD_E_NO_READERS_AVAILABLE;
03143         goto end;
03144     }
03145 
03146     if (SCARD_AUTOALLOCATE == *pcchReaders)
03147     {
03148         buf = malloc(dwReadersLen);
03149         if (NULL == buf)
03150         {
03151             rv = SCARD_E_NO_MEMORY;
03152             goto end;
03153         }
03154         *(char **)mszReaders = buf;
03155     }
03156     else
03157     {
03158         buf = mszReaders;
03159 
03160         /* not enough place to store the reader names */
03161         if ((NULL != mszReaders) && (*pcchReaders < dwReadersLen))
03162         {
03163             rv = SCARD_E_INSUFFICIENT_BUFFER;
03164             goto end;
03165         }
03166     }
03167 
03168     if (mszReaders == NULL) /* text array not allocated */
03169         goto end;
03170 
03171     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
03172     {
03173         if ((readerStates[i])->readerID != 0)
03174         {
03175             /*
03176              * Build the multi-string
03177              */
03178             strcpy(buf, (readerStates[i])->readerName);
03179             buf += strlen((readerStates[i])->readerName)+1;
03180         }
03181     }
03182     *buf = '\0';    /* Add the last null */
03183 
03184 end:
03185     /* set the reader names length */
03186     *pcchReaders = dwReadersLen;
03187 
03188     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03189 
03190     PROFILE_END(rv)
03191 
03192     return rv;
03193 }
03194 
03207 LONG SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)
03208 {
03209     LONG rv = SCARD_S_SUCCESS;
03210     LONG dwContextIndex;
03211 
03212     PROFILE_START
03213 
03214     rv = SCardCheckDaemonAvailability();
03215     if (rv != SCARD_S_SUCCESS)
03216         return rv;
03217 
03218     /*
03219      * Make sure this context has been opened
03220      */
03221     dwContextIndex = SCardGetContextIndice(hContext);
03222     if (dwContextIndex == -1)
03223         return SCARD_E_INVALID_HANDLE;
03224 
03225     free((void *)pvMem);
03226 
03227     PROFILE_END(rv)
03228 
03229     return rv;
03230 }
03231 
03266 LONG SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups,
03267     LPDWORD pcchGroups)
03268 {
03269     LONG rv = SCARD_S_SUCCESS;
03270     LONG dwContextIndex;
03271     char *buf = NULL;
03272 
03273     PROFILE_START
03274 
03275     /* Multi-string with two trailing \0 */
03276     const char ReaderGroup[] = "SCard$DefaultReaders\0";
03277     const int dwGroups = sizeof(ReaderGroup);
03278 
03279     rv = SCardCheckDaemonAvailability();
03280     if (rv != SCARD_S_SUCCESS)
03281         return rv;
03282 
03283     /*
03284      * Make sure this context has been opened
03285      */
03286     dwContextIndex = SCardGetContextIndice(hContext);
03287     if (dwContextIndex == -1)
03288         return SCARD_E_INVALID_HANDLE;
03289 
03290     SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
03291 
03292     /* check the context is still opened */
03293     dwContextIndex = SCardGetContextIndice(hContext);
03294     if (dwContextIndex == -1)
03295         /* the context is now invalid
03296          * -> another thread may have called SCardReleaseContext
03297          * -> so the mMutex has been unlocked */
03298         return SCARD_E_INVALID_HANDLE;
03299 
03300     if (SCARD_AUTOALLOCATE == *pcchGroups)
03301     {
03302         buf = malloc(dwGroups);
03303         if (NULL == buf)
03304         {
03305             rv = SCARD_E_NO_MEMORY;
03306             goto end;
03307         }
03308         *(char **)mszGroups = buf;
03309     }
03310     else
03311     {
03312         buf = mszGroups;
03313 
03314         if ((NULL != mszGroups) && (*pcchGroups < dwGroups))
03315         {
03316             rv = SCARD_E_INSUFFICIENT_BUFFER;
03317             goto end;
03318         }
03319     }
03320 
03321     if (buf)
03322         memcpy(buf, ReaderGroup, dwGroups);
03323 
03324 end:
03325     *pcchGroups = dwGroups;
03326 
03327     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
03328 
03329     PROFILE_END(rv)
03330 
03331     return rv;
03332 }
03333 
03362 LONG SCardCancel(SCARDCONTEXT hContext)
03363 {
03364     LONG dwContextIndex;
03365 
03366     PROFILE_START
03367 
03368     dwContextIndex = SCardGetContextIndice(hContext);
03369     if (dwContextIndex == -1)
03370         return SCARD_E_INVALID_HANDLE;
03371 
03372     /*
03373      * Set the block status for this Context so blocking calls will
03374      * complete
03375      */
03376     psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_RESUME;
03377 
03378     PROFILE_END(SCARD_S_SUCCESS)
03379 
03380     return SCARD_S_SUCCESS;
03381 }
03382 
03407 LONG SCardIsValidContext(SCARDCONTEXT hContext)
03408 {
03409     LONG rv;
03410     LONG dwContextIndex;
03411 
03412     PROFILE_START
03413 
03414     rv = SCARD_S_SUCCESS;
03415 
03416     /* Check if the _same_ server is running */
03417     rv = SCardCheckDaemonAvailability();
03418     if (rv != SCARD_S_SUCCESS)
03419         return rv;
03420 
03421     /*
03422      * Make sure this context has been opened
03423      */
03424     dwContextIndex = SCardGetContextIndice(hContext);
03425     if (dwContextIndex == -1)
03426         rv = SCARD_E_INVALID_HANDLE;
03427 
03428     PROFILE_END(rv)
03429 
03430     return rv;
03431 }
03432 
03449 static LONG SCardAddContext(SCARDCONTEXT hContext, DWORD dwClientID)
03450 {
03451     int i;
03452 
03453     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03454     {
03455         if (psContextMap[i].hContext == 0)
03456         {
03457             psContextMap[i].hContext = hContext;
03458             psContextMap[i].dwClientID = dwClientID;
03459             psContextMap[i].contextBlockStatus = BLOCK_STATUS_RESUME;
03460             psContextMap[i].mMutex = malloc(sizeof(PCSCLITE_MUTEX));
03461             SYS_MutexInit(psContextMap[i].mMutex);
03462             return SCARD_S_SUCCESS;
03463         }
03464     }
03465 
03466     return SCARD_E_NO_MEMORY;
03467 }
03468 
03481 static LONG SCardGetContextIndice(SCARDCONTEXT hContext)
03482 {
03483     LONG rv;
03484 
03485     SCardLockThread();
03486     rv = SCardGetContextIndiceTH(hContext);
03487     SCardUnlockThread();
03488 
03489     return rv;
03490 }
03491 
03504 static LONG SCardGetContextIndiceTH(SCARDCONTEXT hContext)
03505 {
03506     int i;
03507 
03508     /*
03509      * Find this context and return it's spot in the array
03510      */
03511     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03512     {
03513         if ((hContext == psContextMap[i].hContext) && (hContext != 0))
03514             return i;
03515     }
03516 
03517     return -1;
03518 }
03519 
03529 static LONG SCardRemoveContext(SCARDCONTEXT hContext)
03530 {
03531     LONG  retIndice;
03532 
03533     retIndice = SCardGetContextIndiceTH(hContext);
03534 
03535     if (retIndice == -1)
03536         return SCARD_E_INVALID_HANDLE;
03537     else
03538         return SCardCleanContext(retIndice);
03539 }
03540 
03541 static LONG SCardCleanContext(LONG indice)
03542 {
03543     int i;
03544 
03545     psContextMap[indice].hContext = 0;
03546     SHMClientCloseSession(psContextMap[indice].dwClientID);
03547     psContextMap[indice].dwClientID = 0;
03548     free(psContextMap[indice].mMutex);
03549     psContextMap[indice].mMutex = NULL;
03550     psContextMap[indice].contextBlockStatus = BLOCK_STATUS_RESUME;
03551 
03552     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03553     {
03554         /*
03555          * Reset the \c hCard structs to zero
03556          */
03557         psContextMap[indice].psChannelMap[i].hCard = 0;
03558         free(psContextMap[indice].psChannelMap[i].readerName);
03559         psContextMap[indice].psChannelMap[i].readerName = NULL;
03560     }
03561 
03562     return SCARD_S_SUCCESS;
03563 }
03564 
03565 /*
03566  * Functions for managing hCard values returned from SCardConnect.
03567  */
03568 
03569 static LONG SCardAddHandle(SCARDHANDLE hCard, DWORD dwContextIndex,
03570     LPCSTR readerName)
03571 {
03572     int i;
03573 
03574     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03575     {
03576         if (psContextMap[dwContextIndex].psChannelMap[i].hCard == 0)
03577         {
03578             psContextMap[dwContextIndex].psChannelMap[i].hCard = hCard;
03579             psContextMap[dwContextIndex].psChannelMap[i].readerName = strdup(readerName);
03580             return SCARD_S_SUCCESS;
03581         }
03582     }
03583 
03584     return SCARD_E_NO_MEMORY;
03585 }
03586 
03587 static LONG SCardRemoveHandle(SCARDHANDLE hCard)
03588 {
03589     DWORD dwContextIndice, dwChannelIndice;
03590     LONG rv;
03591 
03592     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndice, &dwChannelIndice);
03593     if (rv == -1)
03594         return SCARD_E_INVALID_HANDLE;
03595     else
03596     {
03597         psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].hCard = 0;
03598         free(psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName);
03599         psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName = NULL;
03600         return SCARD_S_SUCCESS;
03601     }
03602 }
03603 
03604 static LONG SCardGetIndicesFromHandle(SCARDHANDLE hCard,
03605     PDWORD pdwContextIndice, PDWORD pdwChannelIndice)
03606 {
03607     LONG rv;
03608 
03609     if (0 == hCard)
03610         return -1;
03611 
03612     SCardLockThread();
03613     rv = SCardGetIndicesFromHandleTH(hCard, pdwContextIndice, pdwChannelIndice);
03614     SCardUnlockThread();
03615 
03616     return rv;
03617 }
03618 
03619 static LONG SCardGetIndicesFromHandleTH(SCARDHANDLE hCard,
03620     PDWORD pdwContextIndice, PDWORD pdwChannelIndice)
03621 {
03622     int i;
03623 
03624     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03625     {
03626         if (psContextMap[i].hContext != 0)
03627         {
03628             int j;
03629 
03630             for (j = 0; j < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; j++)
03631             {
03632                 if (psContextMap[i].psChannelMap[j].hCard == hCard)
03633                 {
03634                     *pdwContextIndice = i;
03635                     *pdwChannelIndice = j;
03636                     return SCARD_S_SUCCESS;
03637                 }
03638             }
03639 
03640         }
03641     }
03642 
03643     return -1;
03644 }
03645 
03654 LONG SCardCheckDaemonAvailability(void)
03655 {
03656     LONG rv;
03657     struct stat statBuffer;
03658     int need_restart = 0;
03659 
03660     rv = SYS_Stat(PCSCLITE_PUBSHM_FILE, &statBuffer);
03661 
03662     if (rv != 0)
03663     {
03664         Log2(PCSC_LOG_INFO, "PCSC Not Running: " PCSCLITE_PUBSHM_FILE ": %s",
03665             strerror(errno));
03666         return SCARD_E_NO_SERVICE;
03667     }
03668 
03669     /* when the _first_ reader is connected the ctime changes
03670      * I don't know why yet */
03671     if (daemon_ctime && statBuffer.st_ctime > daemon_ctime)
03672     {
03673         /* so we also check the daemon pid to be sure it is a new pcscd */
03674         if (GetDaemonPid() != daemon_pid)
03675         {
03676             Log1(PCSC_LOG_INFO, "PCSC restarted");
03677             need_restart = 1;
03678         }
03679     }
03680 
03681     /* after fork() need to restart */
03682     if (client_pid && client_pid != getpid())
03683     {
03684         Log1(PCSC_LOG_INFO, "Client forked");
03685         need_restart = 1;
03686     }
03687 
03688     if (need_restart)
03689     {
03690         int i;
03691 
03692         /* invalid all handles */
03693         SCardLockThread();
03694 
03695         for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03696             if (psContextMap[i].hContext)
03697                 SCardCleanContext(i);
03698 
03699         SCardUnlockThread();
03700 
03701         /* reset pcscd status */
03702         daemon_ctime = 0;
03703         client_pid = 0;
03704 
03705         /* reset the lib */
03706         SCardUnload();
03707 
03708         return SCARD_E_INVALID_HANDLE;
03709     }
03710 
03711     daemon_ctime = statBuffer.st_ctime;
03712     daemon_pid = GetDaemonPid();
03713     client_pid = getpid();
03714 
03715     return SCARD_S_SUCCESS;
03716 }
03717 
03723 #ifdef __SUNPRO_C
03724 #pragma fini (SCardUnload)
03725 #endif
03726 
03727 void DESTRUCTOR SCardUnload(void)
03728 {
03729     int i;
03730 
03731     if (!isExecuted)
03732         return;
03733 
03734     /* unmap public shared file from memory */
03735     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03736     {
03737         if (readerStates[i] != NULL)
03738         {
03739             SYS_PublicMemoryUnmap(readerStates[i], sizeof(READER_STATE));
03740             readerStates[i] = NULL;
03741         }
03742     }
03743 
03744     SYS_CloseFile(mapAddr);
03745     isExecuted = 0;
03746 }
03747 

Generated on Thu Aug 28 20:14:13 2008 for pcsc-lite by  doxygen 1.5.6