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 1882 2006-02-24 17:05:51Z rousseau $
00010  */
00011 
00020 #include "config.h"
00021 #include <stdlib.h>
00022 #include <string.h>
00023 #include <sys/types.h>
00024 #include <fcntl.h>
00025 #include <unistd.h>
00026 #include <sys/un.h>
00027 #include <errno.h>
00028 
00029 #include "misc.h"
00030 #include "pcsclite.h"
00031 #include "winscard.h"
00032 #include "debuglog.h"
00033 #include "thread_generic.h"
00034 
00035 #include "readerfactory.h"
00036 #include "eventhandler.h"
00037 #include "sys_generic.h"
00038 #include "winscard_msg.h"
00039 
00041 #define SCARD_PROTOCOL_ANY_OLD  0x1000
00042 
00043 #ifndef min
00044 #define min(a,b) (((a) < (b)) ? (a) : (b))
00045 #endif
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 
00063 #define PROFILE_START profile_start(__FUNCTION__);
00064 #define PROFILE_END profile_end(__FUNCTION__);
00065 
00066 static void profile_start(const char *f)
00067 {
00068     static char initialized = FALSE;
00069 
00070     if (!initialized)
00071     {
00072         initialized = TRUE;
00073         fd = fopen(PROFILE_FILE, "a+");
00074         if (NULL == fd)
00075         {
00076             fprintf(stderr, "\33[01;31mCan't open %s: %s\33[0m\n",
00077                 PROFILE_FILE, strerror(errno));
00078             exit(-1);
00079         }
00080         fprintf(fd, "\nStart a new profile\n");
00081 
00082         if (isatty(fileno(stderr)))
00083             profile_tty = TRUE;
00084         else
00085             profile_tty = FALSE;
00086     }
00087 
00088     gettimeofday(&profile_time_start, NULL);
00089 } /* profile_start */
00090 
00091 /* r = a - b */
00092 static long int time_sub(struct timeval *a, struct timeval *b)
00093 {
00094     struct timeval r;
00095     r.tv_sec = a -> tv_sec - b -> tv_sec;
00096     r.tv_usec = a -> tv_usec - b -> tv_usec;
00097     if (r.tv_usec < 0)
00098     {
00099         r.tv_sec--;
00100         r.tv_usec += 1000000;
00101     }
00102 
00103     return r.tv_sec * 1000000 + r.tv_usec;
00104 } /* time_sub */
00105     
00106 
00107 static void profile_end(const char *f)
00108 {
00109     struct timeval profile_time_end;
00110     long d;
00111 
00112     gettimeofday(&profile_time_end, NULL);
00113     d = time_sub(&profile_time_end, &profile_time_start);
00114 
00115     if (profile_tty)
00116         fprintf(stderr, "\33[01;31mRESULT %s \33[35m%ld\33[0m\n", f, d);
00117     fprintf(fd, "%s %ld\n", f, d);
00118 } /* profile_end */
00119 
00120 #else
00121 #define PROFILE_START
00122 #define PROFILE_END
00123 #endif
00124 
00129 struct _psChannelMap
00130 {
00131     SCARDHANDLE hCard;
00132     LPTSTR readerName;
00133 };
00134 
00135 typedef struct _psChannelMap CHANNEL_MAP, *PCHANNEL_MAP;
00136 
00142 static struct _psContextMap
00143 {
00144     DWORD dwClientID;               
00145     SCARDCONTEXT hContext;          
00146     DWORD contextBlockStatus;
00147     PCSCLITE_MUTEX_T mMutex;        
00148     CHANNEL_MAP psChannelMap[PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS];
00149 } psContextMap[PCSCLITE_MAX_APPLICATION_CONTEXTS];
00150 
00154 static short isExecuted = 0;
00155 
00161 static int mapAddr = 0;
00162 
00167 static PCSCLITE_MUTEX clientMutex = PTHREAD_MUTEX_INITIALIZER;
00168 
00175 static PREADER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS];
00176 
00177 PCSC_API SCARD_IO_REQUEST g_rgSCardT0Pci = { SCARD_PROTOCOL_T0, 8 };
00178 PCSC_API SCARD_IO_REQUEST g_rgSCardT1Pci = { SCARD_PROTOCOL_T1, 8 };
00179 PCSC_API SCARD_IO_REQUEST g_rgSCardRawPci = { SCARD_PROTOCOL_RAW, 8 };
00180 
00181 
00182 static LONG SCardAddContext(SCARDCONTEXT, DWORD);
00183 static LONG SCardGetContextIndice(SCARDCONTEXT);
00184 static LONG SCardGetContextIndiceTH(SCARDCONTEXT);
00185 static LONG SCardRemoveContext(SCARDCONTEXT);
00186 
00187 static LONG SCardAddHandle(SCARDHANDLE, DWORD, LPTSTR);
00188 static LONG SCardGetIndicesFromHandle(SCARDHANDLE, PDWORD, PDWORD);
00189 static LONG SCardGetIndicesFromHandleTH(SCARDHANDLE, PDWORD, PDWORD);
00190 static LONG SCardRemoveHandle(SCARDHANDLE);
00191 
00192 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
00193     LPBYTE pbAttr, LPDWORD pcbAttrLen);
00194 
00195 static LONG SCardCheckDaemonAvailability(void);
00196 
00197 /*
00198  * Thread safety functions
00199  */
00200 inline static LONG SCardLockThread(void);
00201 inline static LONG SCardUnlockThread(void);
00202 
00203 static LONG SCardEstablishContextTH(DWORD, LPCVOID, LPCVOID, LPSCARDCONTEXT);
00204 
00237 LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
00238     LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
00239 {
00240     LONG rv;
00241 
00242     PROFILE_START
00243 
00244     SCardLockThread();
00245     rv = SCardEstablishContextTH(dwScope, pvReserved1,
00246         pvReserved2, phContext);
00247     SCardUnlockThread();
00248 
00249     PROFILE_END
00250 
00251     return rv;
00252 }
00253 
00279 static LONG SCardEstablishContextTH(DWORD dwScope, LPCVOID pvReserved1,
00280     LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
00281 {
00282     LONG rv;
00283     int i;
00284     establish_struct scEstablishStruct;
00285     sharedSegmentMsg msgStruct;
00286     DWORD dwClientID = 0;
00287 
00288     if (phContext == NULL)
00289         return SCARD_E_INVALID_PARAMETER;
00290     else
00291         *phContext = 0;
00292 
00293     /* Check if the server is running */
00294     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
00295         return SCARD_E_NO_SERVICE;
00296 
00297     /*
00298      * Do this only once:
00299      * - Initialize debug of need.
00300      * - Set up the memory mapped structures for reader states.
00301      * - Allocate each reader structure.
00302      * - Initialize context struct.
00303      */
00304     if (isExecuted == 0)
00305     {
00306         int pageSize;
00307 
00308         /*
00309          * Initialize debug
00310          */
00311         if (getenv("MUSCLECARD_DEBUG"))
00312         {
00313             DebugLogSetLogType(DEBUGLOG_STDERR_DEBUG);
00314             DebugLogSetLevel(PCSC_LOG_DEBUG);
00315         }
00316 
00317         /*
00318          * Do any system initilization here
00319          */
00320         SYS_Initialize();
00321 
00322         /*
00323          * Set up the memory mapped reader stats structures
00324          */
00325         mapAddr = SYS_OpenFile(PCSCLITE_PUBSHM_FILE, O_RDONLY, 0);
00326         if (mapAddr < 0)
00327         {
00328             Log2(PCSC_LOG_CRITICAL, "Cannot open public shared file: %s",
00329                 PCSCLITE_PUBSHM_FILE);
00330             return SCARD_E_NO_SERVICE;
00331         }
00332 
00333         pageSize = SYS_GetPageSize();
00334 
00335         /*
00336          * Allocate each reader structure in the memory map
00337          */
00338         for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
00339         {
00340             readerStates[i] = (PREADER_STATE)
00341                 SYS_PublicMemoryMap(sizeof(READER_STATE),
00342                 mapAddr, (i * pageSize));
00343             if (readerStates[i] == NULL)
00344             {
00345                 Log1(PCSC_LOG_CRITICAL, "Cannot public memory map");
00346                 SYS_CloseFile(mapAddr); /* Close the memory map file */
00347                 return SCARD_F_INTERNAL_ERROR;
00348             }
00349         }
00350 
00351         /*
00352          * Initializes the application contexts and all channels for each one
00353          */
00354         for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
00355         {
00356             int j;
00357 
00358             /*
00359              * Initially set the context struct to zero
00360              */
00361             psContextMap[i].dwClientID = 0;
00362             psContextMap[i].hContext = 0;
00363             psContextMap[i].contextBlockStatus = BLOCK_STATUS_RESUME;
00364             psContextMap[i].mMutex = NULL;
00365 
00366             for (j = 0; j < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; j++)
00367             {
00368                 /*
00369                  * Initially set the hcard structs to zero
00370                  */
00371                 psContextMap[i].psChannelMap[j].hCard = 0;
00372                 psContextMap[i].psChannelMap[j].readerName = NULL;
00373             }
00374         }
00375 
00376     }
00377 
00378     /*
00379      * Is there a free slot for this connection ?
00380      */
00381 
00382     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
00383     {
00384         if (psContextMap[i].dwClientID == 0)
00385             break;
00386     }
00387 
00388     if (i == PCSCLITE_MAX_APPLICATION_CONTEXTS)
00389     {
00390         return SCARD_E_NO_MEMORY;
00391     }
00392 
00393     /* Establishes a connection to the server */
00394     if (SHMClientSetupSession(&dwClientID) != 0)
00395     {
00396         SYS_CloseFile(mapAddr);
00397         return SCARD_E_NO_SERVICE;
00398     }
00399 
00400     {   /* exchange client/server protocol versions */
00401         sharedSegmentMsg msgStruct;
00402         version_struct *veStr;
00403 
00404         memset(&msgStruct, 0, sizeof(msgStruct));
00405         msgStruct.mtype = CMD_VERSION;
00406         msgStruct.user_id = SYS_GetUID();
00407         msgStruct.group_id = SYS_GetGID();
00408         msgStruct.command = 0;
00409         msgStruct.date = time(NULL);
00410 
00411         veStr = (version_struct *) msgStruct.data;
00412         veStr->major = PROTOCOL_VERSION_MAJOR;
00413         veStr->minor = PROTOCOL_VERSION_MINOR;
00414 
00415         if (-1 == SHMMessageSend(&msgStruct, dwClientID,
00416             PCSCLITE_MCLIENT_ATTEMPTS))
00417             return SCARD_E_NO_SERVICE;
00418 
00419         /*
00420          * Read a message from the server
00421          */
00422         if (-1 == SHMMessageReceive(&msgStruct, dwClientID,
00423             PCSCLITE_CLIENT_ATTEMPTS))
00424         {
00425             Log1(PCSC_LOG_CRITICAL, "Your pcscd is too old and does not support CMD_VERSION");
00426             return SCARD_F_COMM_ERROR;
00427         }
00428 
00429         Log3(PCSC_LOG_INFO, "Server is protocol version %d:%d",
00430             veStr->major, veStr->minor);
00431 
00432         isExecuted = 1;
00433     }
00434 
00435 
00436     if (dwScope != SCARD_SCOPE_USER && dwScope != SCARD_SCOPE_TERMINAL &&
00437         dwScope != SCARD_SCOPE_SYSTEM && dwScope != SCARD_SCOPE_GLOBAL)
00438     {
00439         return SCARD_E_INVALID_VALUE;
00440     }
00441 
00442     /*
00443      * Try to establish an Application Context with the server
00444      */
00445     scEstablishStruct.dwScope = dwScope;
00446     scEstablishStruct.phContext = 0;
00447     scEstablishStruct.rv = 0;
00448 
00449     rv = WrapSHMWrite(SCARD_ESTABLISH_CONTEXT, dwClientID,
00450         sizeof(scEstablishStruct), PCSCLITE_MCLIENT_ATTEMPTS,
00451         (void *) &scEstablishStruct);
00452 
00453     if (rv == -1)
00454         return SCARD_E_NO_SERVICE;
00455 
00456     /*
00457      * Read the response from the server
00458      */
00459     rv = SHMClientRead(&msgStruct, dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
00460 
00461     if (rv == -1)
00462         return SCARD_F_COMM_ERROR;
00463 
00464     memcpy(&scEstablishStruct, &msgStruct.data, sizeof(scEstablishStruct));
00465 
00466     if (scEstablishStruct.rv != SCARD_S_SUCCESS)
00467         return scEstablishStruct.rv;
00468 
00469     *phContext = scEstablishStruct.phContext;
00470 
00471     /*
00472      * Allocate the new hContext - if allocator full return an error
00473      */
00474     rv = SCardAddContext(*phContext, dwClientID);
00475 
00476     return rv;
00477 }
00478 
00497 LONG SCardReleaseContext(SCARDCONTEXT hContext)
00498 {
00499     LONG rv;
00500     release_struct scReleaseStruct;
00501     sharedSegmentMsg msgStruct;
00502     DWORD dwContextIndex;
00503 
00504     PROFILE_START
00505 
00506     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
00507         return SCARD_E_NO_SERVICE;
00508 
00509     /*
00510      * Make sure this context has been opened
00511      */
00512     dwContextIndex = SCardGetContextIndice(hContext);
00513     if (dwContextIndex == -1)
00514         return SCARD_E_INVALID_HANDLE;
00515 
00516     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
00517 
00518     scReleaseStruct.hContext = hContext;
00519     scReleaseStruct.rv = 0;
00520 
00521     rv = WrapSHMWrite(SCARD_RELEASE_CONTEXT, psContextMap[dwContextIndex].dwClientID,
00522               sizeof(scReleaseStruct),
00523               PCSCLITE_MCLIENT_ATTEMPTS, (void *) &scReleaseStruct);
00524 
00525     if (rv == -1)
00526     {
00527         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00528         return SCARD_E_NO_SERVICE;
00529     }
00530 
00531     /*
00532      * Read a message from the server
00533      */
00534     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
00535     memcpy(&scReleaseStruct, &msgStruct.data, sizeof(scReleaseStruct));
00536 
00537     if (rv == -1)
00538     {
00539         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00540         return SCARD_F_COMM_ERROR;
00541     }
00542     
00543     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00544 
00545     /*
00546      * Remove the local context from the stack
00547      */
00548     SCardLockThread();
00549     SCardRemoveContext(hContext);
00550     SCardUnlockThread();
00551 
00552     PROFILE_END
00553 
00554     return scReleaseStruct.rv;
00555 }
00556 
00569 LONG SCardSetTimeout(SCARDCONTEXT hContext, DWORD dwTimeout)
00570 {
00571     /*
00572      * Deprecated
00573      */
00574 
00575     return SCARD_S_SUCCESS;
00576 }
00577 
00626 LONG SCardConnect(SCARDCONTEXT hContext, LPCTSTR szReader,
00627     DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
00628     LPDWORD pdwActiveProtocol)
00629 {
00630     LONG rv;
00631     connect_struct scConnectStruct;
00632     sharedSegmentMsg msgStruct;
00633     DWORD dwContextIndex;
00634 
00635     PROFILE_START
00636 
00637     /*
00638      * Check for NULL parameters
00639      */
00640     if (phCard == NULL || pdwActiveProtocol == NULL)
00641         return SCARD_E_INVALID_PARAMETER;
00642     else
00643         *phCard = 0;
00644 
00645     if (szReader == NULL)
00646         return SCARD_E_UNKNOWN_READER;
00647 
00648     /*
00649      * Check for uninitialized strings
00650      */
00651     if (strlen(szReader) > MAX_READERNAME)
00652         return SCARD_E_INVALID_VALUE;
00653 
00654     if (!(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
00655         !(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
00656         !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
00657         !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
00658     {
00659         return SCARD_E_INVALID_VALUE;
00660     }
00661 
00662     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
00663         return SCARD_E_NO_SERVICE;
00664 
00665     /*
00666      * Make sure this context has been opened
00667      */
00668     dwContextIndex = SCardGetContextIndice(hContext);
00669     if (dwContextIndex == -1)
00670         return SCARD_E_INVALID_HANDLE;
00671 
00672     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
00673 
00674     strncpy(scConnectStruct.szReader, szReader, MAX_READERNAME);
00675 
00676     scConnectStruct.hContext = hContext;
00677     scConnectStruct.dwShareMode = dwShareMode;
00678     scConnectStruct.dwPreferredProtocols = dwPreferredProtocols;
00679     scConnectStruct.phCard = *phCard;
00680     scConnectStruct.pdwActiveProtocol = *pdwActiveProtocol;
00681 
00682     rv = WrapSHMWrite(SCARD_CONNECT, psContextMap[dwContextIndex].dwClientID,
00683         sizeof(scConnectStruct),
00684         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scConnectStruct);
00685 
00686     if (rv == -1)
00687     {
00688         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00689         return SCARD_E_NO_SERVICE;
00690     }
00691 
00692     /*
00693      * Read a message from the server
00694      */
00695     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
00696 
00697     memcpy(&scConnectStruct, &msgStruct.data, sizeof(scConnectStruct));
00698 
00699     if (rv == -1)
00700     {
00701         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00702         return SCARD_F_COMM_ERROR;
00703     }
00704 
00705     *phCard = scConnectStruct.phCard;
00706     *pdwActiveProtocol = scConnectStruct.pdwActiveProtocol;
00707 
00708     if (scConnectStruct.rv == SCARD_S_SUCCESS)
00709     {
00710         /*
00711          * Keep track of the handle locally
00712          */
00713         rv = SCardAddHandle(*phCard, dwContextIndex, (LPTSTR) szReader);
00714         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00715 
00716         PROFILE_END
00717 
00718         return rv;
00719     }
00720 
00721     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00722 
00723     PROFILE_END
00724 
00725     return scConnectStruct.rv;
00726 }
00727 
00793 LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
00794     DWORD dwPreferredProtocols, DWORD dwInitialization,
00795     LPDWORD pdwActiveProtocol)
00796 {
00797     LONG rv;
00798     reconnect_struct scReconnectStruct;
00799     sharedSegmentMsg msgStruct;
00800     int i;
00801     DWORD dwContextIndex, dwChannelIndex;
00802 
00803     PROFILE_START
00804 
00805     if (dwInitialization != SCARD_LEAVE_CARD &&
00806         dwInitialization != SCARD_RESET_CARD &&
00807         dwInitialization != SCARD_UNPOWER_CARD &&
00808         dwInitialization != SCARD_EJECT_CARD)
00809     {
00810         return SCARD_E_INVALID_VALUE;
00811     }
00812 
00813     if (!(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
00814         !(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
00815         !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
00816         !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
00817     {
00818         return SCARD_E_INVALID_VALUE;
00819     }
00820 
00821     if (pdwActiveProtocol == NULL)
00822         return SCARD_E_INVALID_PARAMETER;
00823 
00824     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
00825         return SCARD_E_NO_SERVICE;
00826 
00827     /*
00828      * Make sure this handle has been opened
00829      */
00830     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
00831 
00832     if (rv == -1)
00833         return SCARD_E_INVALID_HANDLE;
00834 
00835     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
00836 
00837 
00838     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
00839     {
00840         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
00841 
00842         /* by default r == NULL */
00843         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
00844             break;
00845     }
00846 
00847     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
00848     {
00849         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00850         return SCARD_E_READER_UNAVAILABLE;
00851     }
00852 
00853     scReconnectStruct.hCard = hCard;
00854     scReconnectStruct.dwShareMode = dwShareMode;
00855     scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
00856     scReconnectStruct.dwInitialization = dwInitialization;
00857     scReconnectStruct.pdwActiveProtocol = *pdwActiveProtocol;
00858 
00859     rv = WrapSHMWrite(SCARD_RECONNECT, psContextMap[dwContextIndex].dwClientID,
00860         sizeof(scReconnectStruct),
00861         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scReconnectStruct);
00862 
00863     if (rv == -1)
00864     {
00865         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00866         return SCARD_E_NO_SERVICE;
00867     }
00868 
00869     /*
00870      * Read a message from the server
00871      */
00872     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
00873 
00874     memcpy(&scReconnectStruct, &msgStruct.data, sizeof(scReconnectStruct));
00875 
00876     if (rv == -1)
00877     {
00878         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00879         return SCARD_F_COMM_ERROR;
00880     }
00881 
00882     *pdwActiveProtocol = scReconnectStruct.pdwActiveProtocol;
00883 
00884     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00885 
00886     PROFILE_END
00887     
00888     return scReconnectStruct.rv;
00889 }
00890 
00921 LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
00922 {
00923     LONG rv;
00924     disconnect_struct scDisconnectStruct;
00925     sharedSegmentMsg msgStruct;
00926     DWORD dwContextIndex, dwChannelIndex;
00927 
00928     PROFILE_START
00929 
00930     if (dwDisposition != SCARD_LEAVE_CARD &&
00931         dwDisposition != SCARD_RESET_CARD &&
00932         dwDisposition != SCARD_UNPOWER_CARD &&
00933         dwDisposition != SCARD_EJECT_CARD)
00934     {
00935         return SCARD_E_INVALID_VALUE;
00936     }
00937 
00938     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
00939         return SCARD_E_NO_SERVICE;
00940 
00941     /*
00942      * Make sure this handle has been opened
00943      */
00944     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
00945 
00946     if (rv == -1)
00947         return SCARD_E_INVALID_HANDLE;
00948 
00949     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
00950 
00951     scDisconnectStruct.hCard = hCard;
00952     scDisconnectStruct.dwDisposition = dwDisposition;
00953 
00954     rv = WrapSHMWrite(SCARD_DISCONNECT, psContextMap[dwContextIndex].dwClientID,
00955         sizeof(scDisconnectStruct),
00956         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scDisconnectStruct);
00957 
00958     if (rv == -1)
00959     {
00960         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00961         return SCARD_E_NO_SERVICE;
00962     }
00963 
00964     /*
00965      * Read a message from the server
00966      */
00967     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
00968 
00969     memcpy(&scDisconnectStruct, &msgStruct.data,
00970         sizeof(scDisconnectStruct));
00971 
00972     if (rv == -1)
00973     {
00974         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00975         return SCARD_F_COMM_ERROR;
00976     }
00977 
00978     SCardRemoveHandle(hCard);
00979 
00980     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
00981 
00982     PROFILE_END
00983 
00984     return scDisconnectStruct.rv;
00985 }
00986 
01019 LONG SCardBeginTransaction(SCARDHANDLE hCard)
01020 {
01021 
01022     LONG rv;
01023     begin_struct scBeginStruct;
01024     int i;
01025     sharedSegmentMsg msgStruct;
01026     DWORD dwContextIndex, dwChannelIndex;
01027 
01028     PROFILE_START
01029 
01030     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01031         return SCARD_E_NO_SERVICE;
01032 
01033     /*
01034      * Make sure this handle has been opened
01035      */
01036     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01037 
01038     if (rv == -1)
01039         return SCARD_E_INVALID_HANDLE;
01040 
01041     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
01042 
01043     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01044     {
01045         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01046 
01047         /* by default r == NULL */
01048         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01049             break;
01050     }
01051 
01052     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01053     {
01054         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01055         return SCARD_E_READER_UNAVAILABLE;
01056     }
01057 
01058     scBeginStruct.hCard = hCard;
01059 
01060     /*
01061      * Query the server every so often until the sharing violation ends
01062      * and then hold the lock for yourself.
01063      */
01064 
01065     do
01066     {
01067         /*
01068          * Look to see if it is locked before polling the server for
01069          * admission to the readers resources
01070          */
01071         if ((readerStates[i])->lockState != 0)
01072         {
01073             int randnum = 0;
01074             int j;
01075 
01076             for (j = 0; j < 100; j++)
01077             {
01078                 /*
01079                  * This helps prevent starvation
01080                  */
01081                 randnum = SYS_RandomInt(1000, 10000);
01082                 SYS_USleep(randnum);
01083 
01084                 if ((readerStates[i])->lockState == 0)
01085                 {
01086                     break;
01087                 }
01088             }
01089         }
01090 
01091         rv = WrapSHMWrite(SCARD_BEGIN_TRANSACTION, psContextMap[dwContextIndex].dwClientID,
01092             sizeof(scBeginStruct),
01093             PCSCLITE_CLIENT_ATTEMPTS, (void *) &scBeginStruct);
01094 
01095         if (rv == -1)
01096         {
01097             
01098             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01099             return SCARD_E_NO_SERVICE;
01100         }
01101 
01102         /*
01103          * Read a message from the server
01104          */
01105         rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
01106 
01107 
01108         memcpy(&scBeginStruct, &msgStruct.data, sizeof(scBeginStruct));
01109 
01110         if (rv == -1)
01111         {
01112             
01113             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01114             return SCARD_F_COMM_ERROR;
01115         }
01116 
01117     }
01118     while (scBeginStruct.rv == SCARD_E_SHARING_VIOLATION);
01119 
01120     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01121 
01122     PROFILE_END
01123 
01124     return scBeginStruct.rv;
01125 }
01126 
01165 LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
01166 {
01167     LONG rv;
01168     end_struct scEndStruct;
01169     sharedSegmentMsg msgStruct;
01170     int randnum, i;
01171     DWORD dwContextIndex, dwChannelIndex;
01172 
01173     PROFILE_START
01174 
01175     /*
01176      * Zero out everything
01177      */
01178     randnum = 0;
01179 
01180     if (dwDisposition != SCARD_LEAVE_CARD &&
01181         dwDisposition != SCARD_RESET_CARD &&
01182         dwDisposition != SCARD_UNPOWER_CARD &&
01183         dwDisposition != SCARD_EJECT_CARD)
01184     {
01185         return SCARD_E_INVALID_VALUE;
01186     }
01187 
01188     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01189         return SCARD_E_NO_SERVICE;
01190 
01191     /*
01192      * Make sure this handle has been opened
01193      */
01194     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01195 
01196     if (rv == -1)
01197         return SCARD_E_INVALID_HANDLE;
01198 
01199     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
01200 
01201     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01202     {
01203         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01204 
01205         /* by default r == NULL */
01206         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01207             break;
01208     }
01209 
01210     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01211     {
01212         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01213         return SCARD_E_READER_UNAVAILABLE;
01214     }
01215 
01216     scEndStruct.hCard = hCard;
01217     scEndStruct.dwDisposition = dwDisposition;
01218 
01219     rv = WrapSHMWrite(SCARD_END_TRANSACTION, psContextMap[dwContextIndex].dwClientID,
01220         sizeof(scEndStruct),
01221         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scEndStruct);
01222 
01223     if (rv == -1)
01224     {
01225         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01226         return SCARD_E_NO_SERVICE;
01227     }
01228 
01229     /*
01230      * Read a message from the server
01231      */
01232     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
01233 
01234     memcpy(&scEndStruct, &msgStruct.data, sizeof(scEndStruct));
01235 
01236     if (rv == -1)
01237     {
01238         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01239         return SCARD_F_COMM_ERROR;
01240     }
01241 
01242     /*
01243      * This helps prevent starvation
01244      */
01245     randnum = SYS_RandomInt(1000, 10000);
01246     SYS_USleep(randnum);
01247 
01248     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01249 
01250     PROFILE_END
01251 
01252     return scEndStruct.rv;
01253 }
01254 
01260 LONG SCardCancelTransaction(SCARDHANDLE hCard)
01261 {
01262     LONG rv;
01263     cancel_struct scCancelStruct;
01264     sharedSegmentMsg msgStruct;
01265     int i;
01266     DWORD dwContextIndex, dwChannelIndex;
01267 
01268     PROFILE_START
01269 
01270     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01271         return SCARD_E_NO_SERVICE;
01272 
01273     /*
01274      * Make sure this handle has been opened
01275      */
01276     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01277 
01278     if (rv == -1)
01279         return SCARD_E_INVALID_HANDLE;
01280 
01281     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
01282 
01283     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01284     {
01285         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01286 
01287         /* by default r == NULL */
01288         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01289             break;
01290     }
01291 
01292     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01293     {
01294         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01295         return SCARD_E_READER_UNAVAILABLE;
01296     }
01297 
01298     scCancelStruct.hCard = hCard;
01299 
01300     rv = WrapSHMWrite(SCARD_CANCEL_TRANSACTION, psContextMap[dwContextIndex].dwClientID,
01301         sizeof(scCancelStruct),
01302         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scCancelStruct);
01303 
01304     if (rv == -1)
01305     {
01306         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01307         return SCARD_E_NO_SERVICE;
01308     }
01309 
01310     /*
01311      * Read a message from the server
01312      */
01313     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
01314 
01315     memcpy(&scCancelStruct, &msgStruct.data, sizeof(scCancelStruct));
01316 
01317     if (rv == -1)
01318     {
01319         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01320         return SCARD_F_COMM_ERROR;
01321     }
01322 
01323     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01324 
01325     PROFILE_END
01326 
01327     return scCancelStruct.rv;
01328 }
01329 
01386 LONG SCardStatus(SCARDHANDLE hCard, LPTSTR mszReaderNames,
01387     LPDWORD pcchReaderLen, LPDWORD pdwState,
01388     LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
01389 {
01390     DWORD dwReaderLen, dwAtrLen;
01391     LONG rv;
01392     int i;
01393     status_struct scStatusStruct;
01394     sharedSegmentMsg msgStruct;
01395     DWORD dwContextIndex, dwChannelIndex;
01396 
01397     PROFILE_START
01398 
01399     /*
01400      * Check for NULL parameters
01401      */
01402 
01403     if (pcchReaderLen == NULL || pcbAtrLen == NULL)
01404         return SCARD_E_INVALID_PARAMETER;
01405 
01406     /* length passed from caller */
01407     dwReaderLen = *pcchReaderLen;
01408     dwAtrLen = *pcbAtrLen;
01409 
01410     /* default output values */
01411     if (pdwState)
01412         *pdwState = 0;
01413 
01414     if (pdwProtocol)
01415         *pdwProtocol = 0;
01416 
01417     *pcchReaderLen = 0;
01418     *pcbAtrLen = 0;
01419 
01420     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01421         return SCARD_E_NO_SERVICE;
01422 
01423     /*
01424      * Make sure this handle has been opened
01425      */
01426     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
01427 
01428     if (rv == -1)
01429         return SCARD_E_INVALID_HANDLE;
01430 
01431     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
01432 
01433     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01434     {
01435         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
01436 
01437         /* by default r == NULL */
01438         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
01439             break;
01440     }
01441 
01442     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01443     {
01444         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01445         return SCARD_E_READER_UNAVAILABLE;
01446     }
01447 
01448     /* initialise the structure */
01449     memset(&scStatusStruct, 0, sizeof(scStatusStruct));
01450     scStatusStruct.hCard = hCard;
01451 
01452     /* those sizes need to be initialised */
01453     scStatusStruct.pcchReaderLen = sizeof(scStatusStruct.mszReaderNames);
01454     scStatusStruct.pcbAtrLen = sizeof(scStatusStruct.pbAtr);
01455 
01456     rv = WrapSHMWrite(SCARD_STATUS, psContextMap[dwContextIndex].dwClientID,
01457         sizeof(scStatusStruct),
01458         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scStatusStruct);
01459 
01460     if (rv == -1)
01461     {
01462         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01463         return SCARD_E_NO_SERVICE;
01464     }
01465 
01466     /*
01467      * Read a message from the server
01468      */
01469     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
01470 
01471     memcpy(&scStatusStruct, &msgStruct.data, sizeof(scStatusStruct));
01472 
01473     if (rv == -1)
01474     {
01475         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01476         return SCARD_F_COMM_ERROR;
01477     }
01478 
01479     rv = scStatusStruct.rv;
01480     if (rv != SCARD_S_SUCCESS && rv != SCARD_E_INSUFFICIENT_BUFFER)
01481     {
01482         /*
01483          * An event must have occurred
01484          */
01485         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01486         return rv;
01487     }
01488 
01489     /*
01490      * Now continue with the client side SCardStatus
01491      */
01492 
01493     *pcchReaderLen = strlen(psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName) + 1;
01494     *pcbAtrLen = (readerStates[i])->cardAtrLength;
01495 
01496     if (pdwState)
01497         *pdwState = (readerStates[i])->readerState;
01498 
01499     if (pdwProtocol)
01500         *pdwProtocol = (readerStates[i])->cardProtocol;
01501 
01502     /* return SCARD_E_INSUFFICIENT_BUFFER only if buffer pointer is non NULL */
01503     if (mszReaderNames)
01504     {
01505         if (*pcchReaderLen > dwReaderLen)
01506             rv = SCARD_E_INSUFFICIENT_BUFFER;
01507 
01508         strncpy(mszReaderNames, 
01509             psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName, 
01510             dwReaderLen);
01511     }
01512 
01513     if (pbAtr)
01514     {
01515         if (*pcbAtrLen > dwAtrLen)
01516             rv = SCARD_E_INSUFFICIENT_BUFFER;
01517 
01518         memcpy(pbAtr, (readerStates[i])->cardAtr,
01519             min(*pcbAtrLen, dwAtrLen));
01520     }
01521     
01522     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01523 
01524     PROFILE_END
01525 
01526     return rv;
01527 }
01528 
01614 LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout,
01615     LPSCARD_READERSTATE_A rgReaderStates, DWORD cReaders)
01616 {
01617     PSCARD_READERSTATE_A currReader;
01618     PREADER_STATE rContext;
01619     DWORD dwTime = 0;
01620     DWORD dwState;
01621     DWORD dwBreakFlag = 0;
01622     int j;
01623     DWORD dwContextIndex;
01624     int currentReaderCount = 0;
01625 
01626     PROFILE_START
01627 
01628     if (rgReaderStates == NULL && cReaders > 0)
01629         return SCARD_E_INVALID_PARAMETER;
01630 
01631     if (cReaders < 0)
01632         return SCARD_E_INVALID_VALUE;
01633 
01634     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01635         return SCARD_E_NO_SERVICE;
01636 
01637     /*
01638      * Make sure this context has been opened
01639      */
01640 
01641     dwContextIndex = SCardGetContextIndice(hContext);
01642     if (dwContextIndex == -1)
01643         return SCARD_E_INVALID_HANDLE;
01644 
01645     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
01646 
01647     /*
01648      * Application is waiting for a reader - return the first available
01649      * reader
01650      */
01651 
01652     if (cReaders == 0)
01653     {
01654         while (1)
01655         {
01656             int i;
01657 
01658             if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01659             {
01660                 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01661                 return SCARD_E_NO_SERVICE;
01662             }
01663 
01664             for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01665             {
01666                 if ((readerStates[i])->readerID != 0)
01667                 {
01668                     /*
01669                      * Reader was found
01670                      */
01671                     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01672 
01673                     PROFILE_END
01674 
01675                     return SCARD_S_SUCCESS;
01676                 }
01677             }
01678 
01679             if (dwTimeout == 0)
01680             {
01681                 /*
01682                  * return immediately - no reader available
01683                  */
01684                 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01685                 return SCARD_E_READER_UNAVAILABLE;
01686             }
01687 
01688             SYS_USleep(PCSCLITE_STATUS_WAIT);
01689 
01690             if (dwTimeout != INFINITE)
01691             {
01692                 dwTime += PCSCLITE_STATUS_WAIT;
01693 
01694                 if (dwTime >= (dwTimeout * 1000))
01695                 {
01696                     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01697 
01698                     PROFILE_END
01699 
01700                     return SCARD_E_TIMEOUT;
01701                 }
01702             }
01703         }
01704     }
01705     else
01706         if (cReaders >= PCSCLITE_MAX_READERS_CONTEXTS)
01707         {
01708             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01709             return SCARD_E_INVALID_VALUE;
01710         }
01711 
01712     /*
01713      * Check the integrity of the reader states structures
01714      */
01715 
01716     for (j = 0; j < cReaders; j++)
01717     {
01718         currReader = &rgReaderStates[j];
01719 
01720         if (currReader->szReader == NULL)
01721         {
01722             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01723             return SCARD_E_INVALID_VALUE;
01724         }
01725     }
01726 
01727     /*
01728      * End of search for readers
01729      */
01730 
01731     /*
01732      * Clear the event state for all readers
01733      */
01734     for (j = 0; j < cReaders; j++)
01735     {
01736         currReader = &rgReaderStates[j];
01737         currReader->dwEventState = 0;
01738     }
01739 
01740     /*
01741      * Now is where we start our event checking loop
01742      */
01743 
01744     Log1(PCSC_LOG_DEBUG, "Event Loop Start");
01745 
01746     psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_BLOCKING;
01747 
01748     /* Get the initial reader count on the system */
01749     for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++)
01750         if ((readerStates[j])->readerID != 0)
01751             currentReaderCount++;
01752 
01753     j = 0;
01754 
01755     do
01756     {
01757         int newReaderCount = 0;
01758         char ReaderCountChanged = FALSE;
01759 
01760         if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
01761         {
01762             SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
01763     
01764             PROFILE_END
01765 
01766             return SCARD_E_NO_SERVICE;
01767         }
01768 
01769         if (j == 0)
01770         {
01771             int i;
01772 
01773             for (i=0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01774                 if ((readerStates[i])->readerID != 0)
01775                     newReaderCount++;
01776 
01777             if (newReaderCount != currentReaderCount)
01778             {
01779                 Log1(PCSC_LOG_INFO, "Reader list changed");
01780                 ReaderCountChanged = TRUE;
01781                 currentReaderCount = newReaderCount;
01782             }
01783         }
01784         currReader = &rgReaderStates[j];
01785 
01786     /************ Look for IGNORED readers ****************************/
01787 
01788         if (currReader->dwCurrentState & SCARD_STATE_IGNORE)
01789         {
01790             currReader->dwEventState = SCARD_STATE_IGNORE;
01791         } else
01792         {
01793             LPTSTR lpcReaderName;
01794             int i;
01795 
01796       /************ Looks for correct readernames *********************/
01797 
01798             lpcReaderName = (char *) currReader->szReader;
01799 
01800             for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
01801             {
01802                 if (strcmp(lpcReaderName,
01803                         (readerStates[i])->readerName) == 0)
01804                 {
01805                     break;
01806                 }
01807             }
01808 
01809             /*
01810              * The requested reader name is not recognized
01811              */
01812             if (i == PCSCLITE_MAX_READERS_CONTEXTS)
01813             {
01814                 if (currReader->dwCurrentState & SCARD_STATE_UNKNOWN)
01815                 {
01816                     currReader->dwEventState = SCARD_STATE_UNKNOWN;
01817                 } else
01818                 {
01819                     currReader->dwEventState =
01820                         SCARD_STATE_UNKNOWN | SCARD_STATE_CHANGED;
01821                     /*
01822                      * Spec says use SCARD_STATE_IGNORE but a removed USB
01823                      * reader with eventState fed into currentState will
01824                      * be ignored forever
01825                      */
01826                     dwBreakFlag = 1;
01827                 }
01828             } else
01829             {
01830 
01831                 /*
01832                  * The reader has come back after being away
01833                  */
01834                 if (currReader->dwCurrentState & SCARD_STATE_UNKNOWN)
01835                 {
01836                     currReader->dwEventState |= SCARD_STATE_CHANGED;
01837                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
01838                     dwBreakFlag = 1;
01839                 }
01840 
01841     /*****************************************************************/
01842 
01843                 /*
01844                  * Set the reader status structure
01845                  */
01846                 rContext = readerStates[i];
01847 
01848                 /*
01849                  * Now we check all the Reader States
01850                  */
01851                 dwState = rContext->readerState;
01852 
01853     /*********** Check if the reader is in the correct state ********/
01854                 if (dwState & SCARD_UNKNOWN)
01855                 {
01856                     /*
01857                      * App thinks reader is in bad state and it is
01858                      */
01859                     if (currReader->
01860                         dwCurrentState & SCARD_STATE_UNAVAILABLE)
01861                     {
01862                         currReader->dwEventState = SCARD_STATE_UNAVAILABLE;
01863                     } else
01864                     {
01865                         /*
01866                          * App thinks reader is in good state and it is
01867                          * not
01868                          */
01869                         currReader->dwEventState = SCARD_STATE_CHANGED |
01870                             SCARD_STATE_UNAVAILABLE;
01871                         dwBreakFlag = 1;
01872                     }
01873                 } else
01874                 {
01875                     /*
01876                      * App thinks reader in bad state but it is not
01877                      */
01878                     if (currReader->
01879                         dwCurrentState & SCARD_STATE_UNAVAILABLE)
01880                     {
01881                         currReader->dwEventState &=
01882                             ~SCARD_STATE_UNAVAILABLE;
01883                         currReader->dwEventState |= SCARD_STATE_CHANGED;
01884                         dwBreakFlag = 1;
01885                     }
01886                 }
01887 
01888     /********** Check for card presence in the reader **************/
01889 
01890                 if (dwState & SCARD_PRESENT)
01891                 {
01892                     /* card present but not yet powered up */
01893                     if (0 == rContext->cardAtrLength)
01894                         /* Allow the status thread to convey information */
01895                         SYS_USleep(PCSCLITE_STATUS_POLL_RATE + 10);
01896 
01897                     currReader->cbAtr = rContext->cardAtrLength;
01898                     memcpy(currReader->rgbAtr, rContext->cardAtr,
01899                         currReader->cbAtr);
01900                 } else
01901                 {
01902                     currReader->cbAtr = 0;
01903                 }
01904 
01905                 /*
01906                  * Card is now absent
01907                  */
01908                 if (dwState & SCARD_ABSENT)
01909                 {
01910                     currReader->dwEventState |= SCARD_STATE_EMPTY;
01911                     currReader->dwEventState &= ~SCARD_STATE_PRESENT;
01912                     currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
01913                     currReader->dwEventState &= ~SCARD_STATE_IGNORE;
01914                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
01915                     currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
01916                     currReader->dwEventState &= ~SCARD_STATE_ATRMATCH;
01917                     currReader->dwEventState &= ~SCARD_STATE_MUTE;
01918                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
01919 
01920                     /*
01921                      * After present the rest are assumed
01922                      */
01923                     if (currReader->dwCurrentState & SCARD_STATE_PRESENT ||
01924                         currReader->dwCurrentState & SCARD_STATE_ATRMATCH
01925                         || currReader->
01926                         dwCurrentState & SCARD_STATE_EXCLUSIVE
01927                         || currReader->dwCurrentState & SCARD_STATE_INUSE)
01928                     {
01929                         currReader->dwEventState |= SCARD_STATE_CHANGED;
01930                         dwBreakFlag = 1;
01931                     }
01932 
01933                     /*
01934                      * Card is now present
01935                      */
01936                 } else if (dwState & SCARD_PRESENT)
01937                 {
01938                     currReader->dwEventState |= SCARD_STATE_PRESENT;
01939                     currReader->dwEventState &= ~SCARD_STATE_EMPTY;
01940                     currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
01941                     currReader->dwEventState &= ~SCARD_STATE_IGNORE;
01942                     currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
01943                     currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
01944                     currReader->dwEventState &= ~SCARD_STATE_MUTE;
01945 
01946                     if (currReader->dwCurrentState & SCARD_STATE_EMPTY)
01947                     {
01948                         currReader->dwEventState |= SCARD_STATE_CHANGED;
01949                         dwBreakFlag = 1;
01950                     }
01951 
01952                     if (dwState & SCARD_SWALLOWED)
01953                     {
01954                         if (currReader->dwCurrentState & SCARD_STATE_MUTE)
01955                         {
01956                             currReader->dwEventState |= SCARD_STATE_MUTE;
01957                         } else
01958                         {
01959                             currReader->dwEventState |= SCARD_STATE_MUTE;
01960                             if (currReader->dwCurrentState !=
01961                                 SCARD_STATE_UNAWARE)
01962                             {
01963                                 currReader->dwEventState |=
01964                                     SCARD_STATE_CHANGED;
01965                             }
01966                             dwBreakFlag = 1;
01967                         }
01968                     } else
01969                     {
01970                         /*
01971                          * App thinks card is mute but it is not
01972                          */
01973                         if (currReader->dwCurrentState & SCARD_STATE_MUTE)
01974                         {
01975                             currReader->dwEventState |=
01976                                 SCARD_STATE_CHANGED;
01977                             dwBreakFlag = 1;
01978                         }
01979                     }
01980                 }
01981 
01982                 /*
01983                  * Now figure out sharing modes
01984                  */
01985                 if (rContext->readerSharing == -1)
01986                 {
01987                     currReader->dwEventState |= SCARD_STATE_EXCLUSIVE;
01988                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
01989                     if (currReader->dwCurrentState & SCARD_STATE_INUSE)
01990                     {
01991                         currReader->dwEventState |= SCARD_STATE_CHANGED;
01992                         dwBreakFlag = 1;
01993                     }
01994                 } else if (rContext->readerSharing >= 1)
01995                 {
01996                     /*
01997                      * A card must be inserted for it to be INUSE
01998                      */
01999                     if (dwState & SCARD_PRESENT)
02000                     {
02001                         currReader->dwEventState |= SCARD_STATE_INUSE;
02002                         currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
02003                         if (currReader->
02004                             dwCurrentState & SCARD_STATE_EXCLUSIVE)
02005                         {
02006                             currReader->dwEventState |=
02007                                 SCARD_STATE_CHANGED;
02008                             dwBreakFlag = 1;
02009                         }
02010                     }
02011                 } else if (rContext->readerSharing == 0)
02012                 {
02013                     currReader->dwEventState &= ~SCARD_STATE_INUSE;
02014                     currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
02015 
02016                     if (currReader->dwCurrentState & SCARD_STATE_INUSE)
02017                     {
02018                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02019                         dwBreakFlag = 1;
02020                     } else if (currReader->
02021                         dwCurrentState & SCARD_STATE_EXCLUSIVE)
02022                     {
02023                         currReader->dwEventState |= SCARD_STATE_CHANGED;
02024                         dwBreakFlag = 1;
02025                     }
02026                 }
02027 
02028                 if (currReader->dwCurrentState == SCARD_STATE_UNAWARE)
02029                 {
02030                     /*
02031                      * Break out of the while .. loop and return status
02032                      * once all the status's for all readers is met
02033                      */
02034                     currReader->dwEventState |= SCARD_STATE_CHANGED;
02035                     dwBreakFlag = 1;
02036                 }
02037 
02038             }   /* End of SCARD_STATE_UNKNOWN */
02039 
02040         }   /* End of SCARD_STATE_IGNORE */
02041 
02042         /*
02043          * Counter and resetter
02044          */
02045         j = j + 1;
02046         if (j == cReaders)
02047         {
02048             if (!dwBreakFlag)
02049             {
02050                 /* break if the reader count changed,
02051                  * so that the calling application can update
02052                  * the reader list
02053                  */
02054                 if (ReaderCountChanged)
02055                     break;
02056             }
02057             j = 0;
02058         }
02059 
02060         /*
02061          * Declare all the break conditions
02062          */
02063 
02064         if (psContextMap[dwContextIndex].contextBlockStatus ==
02065             BLOCK_STATUS_RESUME)
02066             break;
02067 
02068         /*
02069          * Break if UNAWARE is set and all readers have been checked
02070          */
02071         if ((dwBreakFlag == 1) && (j == 0))
02072             break;
02073 
02074         /*
02075          * Timeout has occurred and all readers checked
02076          */
02077         if ((dwTimeout == 0) && (j == 0))
02078             break;
02079 
02080         if (dwTimeout != INFINITE && dwTimeout != 0)
02081         {
02082             /*
02083              * If time is greater than timeout and all readers have been
02084              * checked
02085              */
02086             if ((dwTime >= (dwTimeout * 1000)) && (j == 0))
02087             {
02088                 SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02089                 return SCARD_E_TIMEOUT;
02090             }
02091         }
02092 
02093         /*
02094          * Only sleep once for each cycle of reader checks.
02095          */
02096         if (j == 0)
02097         {
02098             SYS_USleep(PCSCLITE_STATUS_WAIT);
02099             dwTime += PCSCLITE_STATUS_WAIT;
02100         }
02101     }
02102     while (1);
02103 
02104     Log1(PCSC_LOG_DEBUG, "Event Loop End");
02105 
02106     if (psContextMap[dwContextIndex].contextBlockStatus ==
02107             BLOCK_STATUS_RESUME)
02108     {
02109         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02110         return SCARD_E_CANCELLED;
02111     }
02112 
02113     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02114 
02115     PROFILE_END
02116 
02117     return SCARD_S_SUCCESS;
02118 }
02119 
02166 LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,
02167     DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
02168     LPDWORD lpBytesReturned)
02169 {
02170     LONG rv;
02171     control_struct scControlStruct;
02172     sharedSegmentMsg msgStruct;
02173     int i;
02174     DWORD dwContextIndex, dwChannelIndex;
02175 
02176     PROFILE_START
02177 
02178     /* 0 bytes received by default */
02179     if (NULL != lpBytesReturned)
02180         *lpBytesReturned = 0;
02181 
02182     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
02183         return SCARD_E_NO_SERVICE;
02184 
02185     /*
02186      * Make sure this handle has been opened
02187      */
02188     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02189 
02190     if (rv == -1)
02191         return SCARD_E_INVALID_HANDLE;
02192 
02193     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
02194 
02195     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02196     {
02197         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02198 
02199         /* by default r == NULL */
02200         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02201             break;
02202     }
02203 
02204     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02205     {
02206         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02207         return SCARD_E_READER_UNAVAILABLE;
02208     }
02209 
02210     if (cbSendLength > MAX_BUFFER_SIZE)
02211     {
02212         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02213         return SCARD_E_INSUFFICIENT_BUFFER;
02214     }
02215 
02216     scControlStruct.hCard = hCard;
02217     scControlStruct.dwControlCode = dwControlCode;
02218     scControlStruct.cbSendLength = cbSendLength;
02219     scControlStruct.cbRecvLength = cbRecvLength;
02220     memcpy(scControlStruct.pbSendBuffer, pbSendBuffer, cbSendLength);
02221 
02222     rv = WrapSHMWrite(SCARD_CONTROL, psContextMap[dwContextIndex].dwClientID,
02223         sizeof(scControlStruct), PCSCLITE_CLIENT_ATTEMPTS, &scControlStruct);
02224 
02225     if (rv == -1)
02226     {
02227         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02228         return SCARD_E_NO_SERVICE;
02229     }
02230 
02231     /*
02232      * Read a message from the server
02233      */
02234     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
02235 
02236     if (rv == -1)
02237     {
02238         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02239         return SCARD_F_COMM_ERROR;
02240     }
02241 
02242     memcpy(&scControlStruct, &msgStruct.data, sizeof(scControlStruct));
02243 
02244     if (NULL != lpBytesReturned)
02245         *lpBytesReturned = scControlStruct.dwBytesReturned;
02246 
02247     if (scControlStruct.rv == SCARD_S_SUCCESS)
02248     {
02249         /*
02250          * Copy and zero it so any secret information is not leaked
02251          */
02252         memcpy(pbRecvBuffer, scControlStruct.pbRecvBuffer,
02253             scControlStruct.cbRecvLength);
02254         memset(scControlStruct.pbRecvBuffer, 0x00,
02255             sizeof(scControlStruct.pbRecvBuffer));
02256     }
02257 
02258     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02259 
02260     PROFILE_END
02261 
02262     return scControlStruct.rv;
02263 }
02264 
02345 LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr,
02346     LPDWORD pcbAttrLen)
02347 {
02348     PROFILE_START
02349 
02350     if (NULL == pcbAttrLen)
02351         return SCARD_E_INVALID_PARAMETER;
02352 
02353     /* if only get the length */
02354     if (NULL == pbAttr)
02355         /* this variable may not be set by the caller. use a reasonable size */
02356         *pcbAttrLen = MAX_BUFFER_SIZE;
02357 
02358     PROFILE_END
02359 
02360     return SCardGetSetAttrib(hCard, SCARD_GET_ATTRIB, dwAttrId, pbAttr,
02361         pcbAttrLen);
02362 }
02363 
02394 LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr,
02395     DWORD cbAttrLen)
02396 {
02397     PROFILE_START
02398 
02399     if (NULL == pbAttr || 0 == cbAttrLen)
02400         return SCARD_E_INVALID_PARAMETER;
02401 
02402     PROFILE_END
02403 
02404     return SCardGetSetAttrib(hCard, SCARD_SET_ATTRIB, dwAttrId, (LPBYTE)pbAttr,
02405         &cbAttrLen);
02406 }
02407 
02408 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
02409     LPBYTE pbAttr, LPDWORD pcbAttrLen)
02410 {
02411     PROFILE_START
02412 
02413     LONG rv;
02414     getset_struct scGetSetStruct;
02415     sharedSegmentMsg msgStruct;
02416     int i;
02417     DWORD dwContextIndex, dwChannelIndex;
02418 
02419     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
02420         return SCARD_E_NO_SERVICE;
02421 
02422     /*
02423      * Make sure this handle has been opened
02424      */
02425     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02426 
02427     if (rv == -1)
02428         return SCARD_E_INVALID_HANDLE;
02429 
02430     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
02431 
02432     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02433     {
02434         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02435 
02436         /* by default r == NULL */
02437         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02438             break;
02439     }
02440 
02441     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02442     {
02443         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02444         return SCARD_E_READER_UNAVAILABLE;
02445     }
02446 
02447     if (*pcbAttrLen > MAX_BUFFER_SIZE)
02448     {
02449         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02450         return SCARD_E_INSUFFICIENT_BUFFER;
02451     }
02452 
02453     scGetSetStruct.hCard = hCard;
02454     scGetSetStruct.dwAttrId = dwAttrId;
02455     scGetSetStruct.cbAttrLen = *pcbAttrLen;
02456     scGetSetStruct.rv = SCARD_E_NO_SERVICE;
02457     if (SCARD_SET_ATTRIB == command)
02458         memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
02459 
02460     rv = WrapSHMWrite(command,
02461         psContextMap[dwContextIndex].dwClientID, sizeof(scGetSetStruct),
02462         PCSCLITE_CLIENT_ATTEMPTS, &scGetSetStruct);
02463 
02464     if (rv == -1)
02465     {
02466         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02467         return SCARD_E_NO_SERVICE;
02468     }
02469 
02470     /*
02471      * Read a message from the server
02472      */
02473     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
02474 
02475     if (rv == -1)
02476     {
02477         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02478         return SCARD_F_COMM_ERROR;
02479     }
02480 
02481     memcpy(&scGetSetStruct, &msgStruct.data, sizeof(scGetSetStruct));
02482 
02483     if ((SCARD_S_SUCCESS == scGetSetStruct.rv) && (SCARD_GET_ATTRIB == command))
02484     {
02485         /*
02486          * Copy and zero it so any secret information is not leaked
02487          */
02488         if (*pcbAttrLen < scGetSetStruct.cbAttrLen)
02489         {
02490             scGetSetStruct.cbAttrLen = *pcbAttrLen;
02491             scGetSetStruct.rv = SCARD_E_INSUFFICIENT_BUFFER;
02492         }
02493         else
02494             *pcbAttrLen = scGetSetStruct.cbAttrLen;
02495 
02496         if (pbAttr)
02497             memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen);
02498 
02499         memset(scGetSetStruct.pbAttr, 0x00, sizeof(scGetSetStruct.pbAttr));
02500     }
02501 
02502     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02503 
02504     PROFILE_END
02505 
02506     return scGetSetStruct.rv;
02507 }
02508 
02562 LONG SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci,
02563     LPCBYTE pbSendBuffer, DWORD cbSendLength,
02564     LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer,
02565     LPDWORD pcbRecvLength)
02566 {
02567     LONG rv;
02568     transmit_struct scTransmitStruct;
02569     sharedSegmentMsg msgStruct;
02570     int i;
02571     DWORD dwContextIndex, dwChannelIndex;
02572 
02573     PROFILE_START
02574 
02575     if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
02576             pcbRecvLength == NULL || pioSendPci == NULL)
02577         return SCARD_E_INVALID_PARAMETER;
02578 
02579     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
02580         return SCARD_E_NO_SERVICE;
02581 
02582     /*
02583      * Make sure this handle has been opened
02584      */
02585     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
02586 
02587     if (rv == -1)
02588     {
02589         *pcbRecvLength = 0;
02590         return SCARD_E_INVALID_HANDLE;
02591     }
02592 
02593     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
02594 
02595     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02596     {
02597         char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
02598 
02599         /* by default r == NULL */
02600         if (r && strcmp(r, (readerStates[i])->readerName) == 0)
02601             break;
02602     }
02603 
02604     if (i == PCSCLITE_MAX_READERS_CONTEXTS)
02605     {
02606         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02607         return SCARD_E_READER_UNAVAILABLE;
02608     }
02609 
02610     if (cbSendLength > MAX_BUFFER_SIZE)
02611     {
02612         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02613         return SCARD_E_INSUFFICIENT_BUFFER;
02614     }
02615 
02616     scTransmitStruct.hCard = hCard;
02617     scTransmitStruct.cbSendLength = cbSendLength;
02618     scTransmitStruct.pcbRecvLength = *pcbRecvLength;
02619     memcpy(&scTransmitStruct.pioSendPci, pioSendPci,
02620         sizeof(SCARD_IO_REQUEST));
02621     memcpy(scTransmitStruct.pbSendBuffer, pbSendBuffer, cbSendLength);
02622 
02623     if (pioRecvPci)
02624     {
02625         memcpy(&scTransmitStruct.pioRecvPci, pioRecvPci,
02626             sizeof(SCARD_IO_REQUEST));
02627     }
02628     else
02629         scTransmitStruct.pioRecvPci.dwProtocol = SCARD_PROTOCOL_ANY;
02630 
02631     rv = WrapSHMWrite(SCARD_TRANSMIT, psContextMap[dwContextIndex].dwClientID,
02632         sizeof(scTransmitStruct),
02633         PCSCLITE_CLIENT_ATTEMPTS, (void *) &scTransmitStruct);
02634 
02635     if (rv == -1)
02636     {
02637         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02638         return SCARD_E_NO_SERVICE;
02639     }
02640 
02641     /*
02642      * Read a message from the server
02643      */
02644     rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
02645 
02646     memcpy(&scTransmitStruct, &msgStruct.data, sizeof(scTransmitStruct));
02647 
02648     if (rv == -1)
02649     {
02650         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02651         return SCARD_F_COMM_ERROR;
02652     }
02653 
02654     /*
02655      * Zero it and free it so any secret information cannot be leaked
02656      */
02657     memset(scTransmitStruct.pbSendBuffer, 0x00, cbSendLength);
02658 
02659     if (scTransmitStruct.rv == SCARD_S_SUCCESS)
02660     {
02661         /*
02662          * Copy and zero it so any secret information is not leaked
02663          */
02664         memcpy(pbRecvBuffer, scTransmitStruct.pbRecvBuffer,
02665             scTransmitStruct.pcbRecvLength);
02666         memset(scTransmitStruct.pbRecvBuffer, 0x00,
02667             scTransmitStruct.pcbRecvLength);
02668 
02669         if (pioRecvPci)
02670             memcpy(pioRecvPci, &scTransmitStruct.pioRecvPci,
02671                 sizeof(SCARD_IO_REQUEST));
02672     }
02673 
02674     *pcbRecvLength = scTransmitStruct.pcbRecvLength;
02675     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02676 
02677     PROFILE_END
02678 
02679     return scTransmitStruct.rv;
02680 }
02681 
02711 LONG SCardListReaders(SCARDCONTEXT hContext, LPCTSTR mszGroups,
02712     LPTSTR mszReaders, LPDWORD pcchReaders)
02713 {
02714     DWORD dwReadersLen;
02715     int i, lastChrPtr;
02716     DWORD dwContextIndex;
02717 
02718     PROFILE_START
02719 
02720     /*
02721      * Check for NULL parameters
02722      */
02723     if (pcchReaders == NULL)
02724         return SCARD_E_INVALID_PARAMETER;
02725 
02726     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
02727         return SCARD_E_NO_SERVICE;
02728 
02729     /*
02730      * Make sure this context has been opened
02731      */
02732     dwContextIndex = SCardGetContextIndice(hContext);
02733     if (dwContextIndex == -1)
02734         return SCARD_E_INVALID_HANDLE;
02735 
02736     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
02737 
02738     dwReadersLen = 0;
02739     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02740         if ((readerStates[i])->readerID != 0)
02741             dwReadersLen += strlen((readerStates[i])->readerName) + 1;
02742 
02743     /* for the last NULL byte */
02744     dwReadersLen += 1;
02745 
02746     if ((mszReaders == NULL)    /* text array not allocated */
02747         || (*pcchReaders == 0)) /* size == 0 */
02748     {
02749         *pcchReaders = dwReadersLen;
02750         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02751         return SCARD_S_SUCCESS;
02752     }
02753     
02754     if (*pcchReaders < dwReadersLen)
02755     {
02756         *pcchReaders = dwReadersLen;
02757         SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02758         return SCARD_E_INSUFFICIENT_BUFFER;
02759     }
02760 
02761     lastChrPtr = 0;
02762     for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
02763     {
02764         if ((readerStates[i])->readerID != 0)
02765         {
02766             /*
02767              * Build the multi-string
02768              */
02769             strcpy(&mszReaders[lastChrPtr], (readerStates[i])->readerName);
02770             lastChrPtr += strlen((readerStates[i])->readerName)+1;
02771         }
02772     }
02773     mszReaders[lastChrPtr] = '\0';  /* Add the last null */
02774 
02775     *pcchReaders = dwReadersLen;
02776 
02777     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02778 
02779     PROFILE_END
02780 
02781     return SCARD_S_SUCCESS;
02782 }
02783 
02815 LONG SCardListReaderGroups(SCARDCONTEXT hContext, LPTSTR mszGroups,
02816     LPDWORD pcchGroups)
02817 {
02818     LONG rv = SCARD_S_SUCCESS;
02819     DWORD dwContextIndex;
02820 
02821     PROFILE_START
02822 
02823     const char ReaderGroup[] = "SCard$DefaultReaders";
02824     const int dwGroups = strlen(ReaderGroup) + 2;
02825 
02826     if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
02827         return SCARD_E_NO_SERVICE;
02828 
02829     /*
02830      * Make sure this context has been opened
02831      */
02832     dwContextIndex = SCardGetContextIndice(hContext);
02833     if (dwContextIndex == -1)
02834         return SCARD_E_INVALID_HANDLE;
02835 
02836     SYS_MutexLock(psContextMap[dwContextIndex].mMutex); 
02837 
02838     if (mszGroups)
02839     {
02840 
02841         if (*pcchGroups < dwGroups)
02842             rv = SCARD_E_INSUFFICIENT_BUFFER;
02843         else
02844         {
02845             memset(mszGroups, 0, dwGroups);
02846             memcpy(mszGroups, ReaderGroup, strlen(ReaderGroup));
02847         }
02848     }
02849 
02850     *pcchGroups = dwGroups;
02851 
02852     SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);   
02853 
02854     PROFILE_END
02855 
02856     return rv;
02857 }
02858 
02886 LONG SCardCancel(SCARDCONTEXT hContext)
02887 {
02888     DWORD dwContextIndex;
02889 
02890     PROFILE_START
02891 
02892     dwContextIndex = SCardGetContextIndice(hContext);
02893 
02894     if (dwContextIndex == -1)
02895         return SCARD_E_INVALID_HANDLE;
02896 
02897     /*
02898      * Set the block status for this Context so blocking calls will
02899      * complete
02900      */
02901     psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_RESUME;
02902 
02903     PROFILE_END
02904 
02905     return SCARD_S_SUCCESS;
02906 }
02907 
02924 static LONG SCardAddContext(SCARDCONTEXT hContext, DWORD dwClientID)
02925 {
02926     int i;
02927 
02928     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
02929     {
02930         if (psContextMap[i].hContext == 0)
02931         {
02932             psContextMap[i].hContext = hContext;
02933             psContextMap[i].dwClientID = dwClientID;
02934             psContextMap[i].contextBlockStatus = BLOCK_STATUS_RESUME;
02935             psContextMap[i].mMutex = (PCSCLITE_MUTEX_T) malloc(sizeof(PCSCLITE_MUTEX));
02936             SYS_MutexInit(psContextMap[i].mMutex);
02937             return SCARD_S_SUCCESS;
02938         }
02939     }
02940 
02941     return SCARD_E_NO_MEMORY;
02942 }
02943 
02956 static LONG SCardGetContextIndice(SCARDCONTEXT hContext)
02957 {
02958     LONG rv;
02959 
02960     SCardLockThread();
02961     rv = SCardGetContextIndiceTH(hContext);
02962     SCardUnlockThread();
02963 
02964     return rv;
02965 }
02966 
02979 static LONG SCardGetContextIndiceTH(SCARDCONTEXT hContext)
02980 {
02981     int i;
02982 
02983     /*
02984      * Find this context and return it's spot in the array
02985      */
02986     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
02987     {
02988         if ((hContext == psContextMap[i].hContext) && (hContext != 0))
02989             return i;
02990     }
02991 
02992     return -1;
02993 }
02994 
03004 static LONG SCardRemoveContext(SCARDCONTEXT hContext)
03005 {
03006     LONG  retIndice;
03007 
03008     retIndice = SCardGetContextIndiceTH(hContext);
03009 
03010     if (retIndice == -1)
03011         return SCARD_E_INVALID_HANDLE;
03012     else
03013     {
03014         int i;
03015 
03016         psContextMap[retIndice].hContext = 0;
03017         SHMClientCloseSession(psContextMap[retIndice].dwClientID);
03018         psContextMap[retIndice].dwClientID = 0;
03019         free(psContextMap[retIndice].mMutex);
03020         psContextMap[retIndice].mMutex = NULL;
03021         psContextMap[retIndice].contextBlockStatus = BLOCK_STATUS_RESUME;
03022 
03023         for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03024         {
03025             /*
03026              * Reset the \c hCard structs to zero
03027              */
03028             psContextMap[retIndice].psChannelMap[i].hCard = 0;
03029             free(psContextMap[retIndice].psChannelMap[i].readerName);
03030             psContextMap[retIndice].psChannelMap[i].readerName = NULL;
03031         }
03032 
03033         return SCARD_S_SUCCESS;
03034     }
03035 }
03036 
03037 /*
03038  * Functions for managing hCard values returned from SCardConnect.
03039  */
03040 
03041 static LONG SCardAddHandle(SCARDHANDLE hCard, DWORD dwContextIndex,
03042     LPTSTR readerName)
03043 {
03044     int i;
03045 
03046     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
03047     {
03048         if (psContextMap[dwContextIndex].psChannelMap[i].hCard == 0)
03049         {
03050             psContextMap[dwContextIndex].psChannelMap[i].hCard = hCard;
03051             psContextMap[dwContextIndex].psChannelMap[i].readerName = strdup(readerName);
03052             return SCARD_S_SUCCESS;
03053         }
03054     }
03055 
03056     return SCARD_E_NO_MEMORY;
03057 }
03058 
03059 static LONG SCardRemoveHandle(SCARDHANDLE hCard)
03060 {
03061     DWORD dwContextIndice, dwChannelIndice;
03062     LONG rv;
03063 
03064     rv = SCardGetIndicesFromHandle(hCard, &dwContextIndice, &dwChannelIndice);
03065 
03066     if (rv == -1)
03067         return SCARD_E_INVALID_HANDLE;
03068     else
03069     {
03070         psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].hCard = 0;
03071         free(psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName);
03072         psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName = NULL;
03073         return SCARD_S_SUCCESS;
03074     }
03075 }
03076 
03077 static LONG SCardGetIndicesFromHandle(SCARDHANDLE hCard, PDWORD pdwContextIndice, PDWORD pdwChannelIndice)
03078 {
03079     LONG rv;
03080 
03081     SCardLockThread();
03082     rv = SCardGetIndicesFromHandleTH(hCard, pdwContextIndice, pdwChannelIndice);
03083     SCardUnlockThread();
03084 
03085     return rv;
03086 }
03087 
03088 static LONG SCardGetIndicesFromHandleTH(SCARDHANDLE hCard, PDWORD pdwContextIndice, PDWORD pdwChannelIndice)
03089 {
03090     int i;
03091 
03092     for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
03093     {
03094         if (psContextMap[i].hContext != 0)
03095         {
03096             int j;
03097 
03098             for (j = 0; j < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; j++)
03099             {
03100                 if (psContextMap[i].psChannelMap[j].hCard == hCard)
03101                 {
03102                     *pdwContextIndice = i;
03103                     *pdwChannelIndice = j;
03104                     return SCARD_S_SUCCESS;
03105                 }
03106             }
03107             
03108         }
03109     }
03110 
03111     return -1;
03112 }
03113 
03120 inline static LONG SCardLockThread(void)
03121 {
03122     return SYS_MutexLock(&clientMutex);
03123 }
03124 
03130 inline static LONG SCardUnlockThread(void)
03131 {
03132     return SYS_MutexUnLock(&clientMutex);
03133 }
03134 
03142 static LONG SCardCheckDaemonAvailability(void)
03143 {
03144     LONG rv;
03145     struct stat statBuffer;
03146 
03147     rv = SYS_Stat(PCSCLITE_IPC_DIR, &statBuffer);
03148 
03149     if (rv != 0)
03150     {
03151         Log1(PCSC_LOG_ERROR, "PCSC Not Running");
03152         return SCARD_E_NO_SERVICE;
03153     }
03154 
03155     return SCARD_S_SUCCESS;
03156 }
03157 
03163 #ifdef __SUNPRO_C
03164 #pragma fini (SCardUnload)
03165 #endif
03166 
03167 void DESTRUCTOR SCardUnload(void)
03168 {
03169     if (!isExecuted)
03170         return;
03171 
03172     SYS_CloseFile(mapAddr);
03173     isExecuted = 0;
03174 }
03175 

Generated on Fri Mar 24 04:30:06 2006 for pcsc-lite by  doxygen 1.4.6